Permalink
Browse files

Merge branch 'master' into session

* master: (55 commits)
  extract deprecated dynamic methods
  Add some docs and changelog entry
  Allow overriding exception handling in threaded consumer
  Allow configuring a different queue consumer
  actually don't need to expand the aggregates at all
  #to_sym is unnecessary
  de-globalise method
  extract code from AR::Base
  clean up implementation of dynamic methods. use method compilation etc.
  Fix ActiveModel README example
  mention database mapping in getting started guide
  Remove vestiges of the http_only! config from configuring guide
  Remove content-length as well
  Make ActionController#head pass rack-link
  RouteSet: optimize routes generation when globbing is used
  Allows assert_redirected_to to accept a regular expression
  use extract_options!
  No need to force conversion to Symbol since case ensures it's already one.
  No need to work around 1.8 warnings anymore.
  Update command line guide
  ...
  • Loading branch information...
2 parents c4f0229 + 510cf0a commit b13849de88cb330aaedee0881862ea55bfa33c85 @tenderlove tenderlove committed May 4, 2012
Showing with 881 additions and 853 deletions.
  1. +1 −1 actionmailer/lib/action_mailer/delivery_methods.rb
  2. +1 −13 actionmailer/test/abstract_unit.rb
  3. +4 −0 actionpack/CHANGELOG.md
  4. +4 −2 actionpack/lib/action_controller/caching/actions.rb
  5. +21 −1 actionpack/lib/action_controller/metal/head.rb
  6. +8 −7 actionpack/lib/action_dispatch/http/headers.rb
  7. +4 −0 actionpack/lib/action_dispatch/http/parameters.rb
  8. +3 −1 actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb
  9. +2 −0 actionpack/lib/action_dispatch/routing/mapper.rb
  10. +2 −1 actionpack/lib/action_dispatch/routing/redirection.rb
  11. +15 −21 actionpack/lib/action_dispatch/routing/route_set.rb
  12. +1 −1 actionpack/lib/action_dispatch/routing/url_for.rb
  13. +20 −13 actionpack/lib/action_dispatch/testing/assertions/response.rb
  14. +26 −9 actionpack/lib/action_view/helpers/form_options_helper.rb
  15. +1 −1 actionpack/lib/action_view/helpers/form_tag_helper.rb
  16. +1 −1 actionpack/lib/action_view/helpers/text_helper.rb
  17. +4 −0 actionpack/test/controller/action_pack_assertions_test.rb
  18. +32 −1 actionpack/test/controller/caching_test.rb
  19. +66 −0 actionpack/test/controller/new_base/bare_metal_test.rb
  20. +5 −0 actionpack/test/dispatch/header_test.rb
  21. +19 −0 actionpack/test/dispatch/routing_test.rb
  22. +1 −1 activemodel/README.rdoc
  23. +6 −0 activerecord/CHANGELOG.md
  24. +0 −2 activerecord/lib/active_record.rb
  25. +9 −3 activerecord/lib/active_record/aggregations.rb
  26. +9 −9 activerecord/lib/active_record/associations.rb
  27. +4 −4 activerecord/lib/active_record/associations/collection_proxy.rb
  28. +4 −1 activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
  29. +0 −108 activerecord/lib/active_record/dynamic_finder_match.rb
  30. +108 −61 activerecord/lib/active_record/dynamic_matchers.rb
  31. +0 −30 activerecord/lib/active_record/dynamic_scope_match.rb
  32. +1 −1 activerecord/lib/active_record/querying.rb
  33. +4 −0 activerecord/lib/active_record/reflection.rb
  34. +1 −1 activerecord/lib/active_record/relation/calculations.rb
  35. +51 −46 activerecord/lib/active_record/relation/finder_methods.rb
  36. +1 −1 activerecord/lib/active_record/sanitization.rb
  37. +5 −0 activerecord/test/cases/associations/has_many_associations_test.rb
  38. +0 −106 activerecord/test/cases/dynamic_finder_match_test.rb
  39. +30 −2 activerecord/test/cases/finder_test.rb
  40. +2 −3 activerecord/test/cases/named_scope_test.rb
  41. +5 −0 activerecord/test/models/company.rb
  42. +1 −1 activesupport/lib/active_support/cache.rb
  43. +1 −1 activesupport/lib/active_support/cache/file_store.rb
  44. +7 −0 activesupport/test/caching_test.rb
  45. BIN guides/assets/images/getting_started/post_with_comments.png
  46. +3 −2 guides/code/getting_started/app/controllers/comments_controller.rb
  47. +2 −0 guides/code/getting_started/app/controllers/posts_controller.rb
  48. +4 −4 guides/code/getting_started/app/views/comments/_comment.html.erb
  49. +6 −6 guides/code/getting_started/app/views/comments/_form.html.erb
  50. +3 −13 guides/code/getting_started/app/views/posts/show.html.erb
  51. +2 −0 guides/source/asset_pipeline.textile
  52. +2 −4 guides/source/command_line.textile
  53. +16 −20 guides/source/configuring.textile
  54. +46 −280 guides/source/getting_started.textile
  55. +33 −33 guides/source/layouts_and_rendering.textile
  56. +1 −2 guides/source/security.textile
  57. +4 −0 railties/CHANGELOG.md
  58. +1 −1 railties/lib/rails/application.rb
  59. +5 −3 railties/lib/rails/application/configuration.rb
  60. +2 −2 railties/lib/rails/application/finisher.rb
  61. +34 −22 railties/lib/rails/commands/dbconsole.rb
  62. +6 −1 railties/lib/rails/engine.rb
  63. +7 −3 railties/lib/rails/queueing.rb
  64. +36 −3 railties/test/application/queue_test.rb
  65. +128 −0 railties/test/commands/dbconsole_test.rb
  66. +19 −0 railties/test/queueing/threaded_consumer_test.rb
  67. +31 −0 railties/test/railties/engine_test.rb
@@ -65,7 +65,7 @@ def wrap_delivery_behavior(mail, method=nil) #:nodoc:
when NilClass
raise "Delivery method cannot be nil"
when Symbol
- if klass = delivery_methods[method.to_sym]
+ if klass = delivery_methods[method]
mail.delivery_method(klass, send(:"#{method}_settings"))
else
raise "Invalid delivery method #{method.inspect}"
@@ -1,16 +1,4 @@
-# Pathname has a warning, so require it first while silencing
-# warnings to shut it up.
-#
-# Also, in 1.9, Bundler creates warnings due to overriding
-# Rubygems methods
-begin
- old, $VERBOSE = $VERBOSE, nil
- require 'pathname'
- require File.expand_path('../../../load_paths', __FILE__)
-ensure
- $VERBOSE = old
-end
-
+require File.expand_path('../../../load_paths', __FILE__)
require 'active_support/core_ext/kernel/reporting'
# These are the normal settings that will be set up by Railties
@@ -1,5 +1,9 @@
## Rails 4.0.0 (unreleased) ##
+* Allows `assert_redirected_to` to match against a regular expression. *Andy Lindeman*
+
+* Add backtrace to development routing error page. *Richard Schneeman*
+
* Replace `include_seconds` boolean argument with `:include_seconds => true` option
in `distance_of_time_in_words` and `time_ago_in_words` signature. *Dmitriy Kiriyenko*
@@ -133,6 +133,8 @@ def initialize(options, &block)
end
def filter(controller)
+ cache_layout = @cache_layout.respond_to?(:call) ? @cache_layout.call(controller) : @cache_layout
+
path_options = if @cache_path.respond_to?(:call)
controller.instance_exec(controller, &@cache_path)
else
@@ -144,13 +146,13 @@ def filter(controller)
body = controller.read_fragment(cache_path.path, @store_options)
unless body
- controller.action_has_layout = false unless @cache_layout
+ controller.action_has_layout = false unless cache_layout
yield
controller.action_has_layout = true
body = controller._save_fragment(cache_path.path, @store_options)
end
- body = controller.render_to_string(:text => body, :layout => true) unless @cache_layout
+ body = controller.render_to_string(:text => body, :layout => true) unless cache_layout
controller.response_body = body
controller.content_type = Mime[cache_path.extension || :html]
@@ -27,8 +27,28 @@ def head(status, options = {})
self.status = status
self.location = url_for(location) if location
- self.content_type = Mime[formats.first] if formats
+
+ if include_content_headers?(self.status)
+ self.content_type = Mime[formats.first] if formats
+ else
+ headers.delete('Content-Type')
+ headers.delete('Content-Length')
+ end
+
self.response_body = " "
end
+
+ private
+ # :nodoc:
+ def include_content_headers?(status)
+ case status
+ when 100..199
+ false
+ when 204, 205, 304
+ false
+ else
+ true
+ end
+ end
end
end
@@ -14,17 +14,18 @@ def initialize(*args)
end
def [](header_name)
- if include?(header_name)
- super
- else
- super(env_name(header_name))
- end
+ super env_name(header_name)
+ end
+
+ def fetch(header_name, default=nil, &block)
+ super env_name(header_name), default, &block
end
private
- # Converts a HTTP header name to an environment variable name.
+ # Converts a HTTP header name to an environment variable name if it is
+ # not contained within the headers hash.
def env_name(header_name)
- @@env_cache[header_name]
+ include?(header_name) ? header_name : @@env_cache[header_name]
end
end
end
@@ -35,6 +35,10 @@ def path_parameters
@env["action_dispatch.request.path_parameters"] ||= {}
end
+ def reset_parameters #:nodoc:
+ @env.delete("action_dispatch.request.parameters")
+ end
+
private
# TODO: Validate that the characters are UTF-8. If they aren't,
@@ -12,4 +12,6 @@
<% end %>
<p>
Try running <code>rake routes</code> for more information on available routes.
-</p>
+</p>
+
+<%= render :template => "rescues/_trace" %>
@@ -35,6 +35,8 @@ def matches?(env)
}
return true
+ ensure
+ req.reset_parameters
end
def call(env)
@@ -1,5 +1,6 @@
require 'action_dispatch/http/request'
require 'active_support/core_ext/uri'
+require 'active_support/core_ext/array/extract_options'
require 'rack/utils'
module ActionDispatch
@@ -99,7 +100,7 @@ module Redirection
# match 'accounts/:name' => redirect(SubdomainRedirector.new('api'))
#
def redirect(*args, &block)
- options = args.last.is_a?(Hash) ? args.pop : {}
+ options = args.extract_options!
status = options.delete(:status) || 301
return OptionRedirect.new(status, options) if options.any?
@@ -184,34 +184,25 @@ def define_named_route_methods(name, route)
def define_url_helper(route, name, options)
selector = url_helper_name(name, options[:only_path])
- if optimize_helper?(route)
- @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1
- remove_possible_method :#{selector}
- def #{selector}(*args)
- if args.size == #{route.required_parts.size} && !args.last.is_a?(Hash) && optimize_routes_generation?
- options = #{options.inspect}.merge!(url_options)
- options[:path] = "#{optimized_helper(route)}"
- ActionDispatch::Http::URL.url_for(options)
- else
- url_for(handle_positional_args(args, #{options.inspect}, #{route.segment_keys.inspect}))
- end
- end
- END_EVAL
- else
- @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1
- remove_possible_method :#{selector}
- def #{selector}(*args)
+ @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1
+ remove_possible_method :#{selector}
+ def #{selector}(*args)
+ if #{optimize_helper?(route)} && args.size == #{route.required_parts.size} && !args.last.is_a?(Hash) && optimize_routes_generation?
+ options = #{options.inspect}.merge!(url_options)
+ options[:path] = "#{optimized_helper(route)}"
+ ActionDispatch::Http::URL.url_for(options)
+ else
url_for(handle_positional_args(args, #{options.inspect}, #{route.segment_keys.inspect}))
end
- END_EVAL
- end
+ end
+ END_EVAL
helpers << selector
end
# Clause check about when we need to generate an optimized helper.
def optimize_helper?(route) #:nodoc:
- route.ast.grep(Journey::Nodes::Star).empty? && route.requirements.except(:controller, :action).empty?
+ route.requirements.except(:controller, :action).empty?
end
# Generates the interpolation to be used in the optimized helper.
@@ -223,7 +214,10 @@ def optimized_helper(route)
end
route.required_parts.each_with_index do |part, i|
- string_route.gsub!(part.inspect, "\#{Journey::Router::Utils.escape_fragment(args[#{i}].to_param)}")
+ # Replace each route parameter
+ # e.g. :id for regular parameter or *path for globbing
+ # with ruby string interpolation code
+ string_route.gsub!(/(\*|:)#{part}/, "\#{Journey::Router::Utils.escape_fragment(args[#{i}].to_param)}")
end
string_route
@@ -68,7 +68,7 @@ module Routing
# This generates, among other things, the method <tt>users_path</tt>. By default,
# this method is accessible from your controllers, views and mailers. If you need
# to access this auto-generated method from other places (such as a model), then
- # you can do that by including ActionController::UrlFor in your class:
+ # you can do that by including Rails.application.routes.url_helpers in your class:
#
# class User < ActiveRecord::Base
# include Rails.application.routes.url_helpers
@@ -53,15 +53,18 @@ def assert_response(type, message = nil)
# # assert that the redirection was to the url for @customer
# assert_redirected_to @customer
#
+ # # asserts that the redirection matches the regular expression
+ # assert_redirected_to %r(\Ahttp://example.org)
+ #
def assert_redirected_to(options = {}, message=nil)
assert_response(:redirect, message)
- return true if options == @response.location
+ return true if options === @response.location
redirect_is = normalize_argument_to_redirection(@response.location)
redirect_expected = normalize_argument_to_redirection(options)
message ||= "Expected response to be a redirect to <#{redirect_expected}> but was a redirect to <#{redirect_is}>"
- assert_equal redirect_expected, redirect_is, message
+ assert_operator redirect_expected, :===, redirect_is, message
end
private
@@ -71,17 +74,21 @@ def parameterize(value)
end
def normalize_argument_to_redirection(fragment)
- case fragment
- when %r{^\w[A-Za-z\d+.-]*:.*}
- fragment
- when String
- @request.protocol + @request.host_with_port + fragment
- when :back
- raise RedirectBackError unless refer = @request.headers["Referer"]
- refer
- else
- @controller.url_for(fragment)
- end.delete("\0\r\n")
+ normalized = case fragment
+ when Regexp
+ fragment
+ when %r{^\w[A-Za-z\d+.-]*:.*}
+ fragment
+ when String
+ @request.protocol + @request.host_with_port + fragment
+ when :back
+ raise RedirectBackError unless refer = @request.headers["Referer"]
+ refer
+ else
+ @controller.url_for(fragment)
+ end
+
+ normalized.respond_to?(:delete) ? normalized.delete("\0\r\n") : normalized
end
end
end
@@ -288,38 +288,55 @@ def time_zone_select(object, method, priority_zones = nil, options = {}, html_op
#
# Examples (call, result):
# options_for_select([["Dollar", "$"], ["Kroner", "DKK"]])
- # <option value="$">Dollar</option>\n<option value="DKK">Kroner</option>
+ # # <option value="$">Dollar</option>
+ # # <option value="DKK">Kroner</option>
#
# options_for_select([ "VISA", "MasterCard" ], "MasterCard")
- # <option>VISA</option>\n<option selected="selected">MasterCard</option>
+ # # <option>VISA</option>
+ # # <option selected="selected">MasterCard</option>
#
# options_for_select({ "Basic" => "$20", "Plus" => "$40" }, "$40")
- # <option value="$20">Basic</option>\n<option value="$40" selected="selected">Plus</option>
+ # # <option value="$20">Basic</option>
+ # # <option value="$40" selected="selected">Plus</option>
#
# options_for_select([ "VISA", "MasterCard", "Discover" ], ["VISA", "Discover"])
- # <option selected="selected">VISA</option>\n<option>MasterCard</option>\n<option selected="selected">Discover</option>
+ # # <option selected="selected">VISA</option>
+ # # <option>MasterCard</option>
+ # # <option selected="selected">Discover</option>
#
# You can optionally provide html attributes as the last element of the array.
#
# Examples:
# options_for_select([ "Denmark", ["USA", {:class => 'bold'}], "Sweden" ], ["USA", "Sweden"])
- # <option value="Denmark">Denmark</option>\n<option value="USA" class="bold" selected="selected">USA</option>\n<option value="Sweden" selected="selected">Sweden</option>
+ # # <option value="Denmark">Denmark</option>
+ # # <option value="USA" class="bold" selected="selected">USA</option>
+ # # <option value="Sweden" selected="selected">Sweden</option>
#
# options_for_select([["Dollar", "$", {:class => "bold"}], ["Kroner", "DKK", {:onclick => "alert('HI');"}]])
- # <option value="$" class="bold">Dollar</option>\n<option value="DKK" onclick="alert('HI');">Kroner</option>
+ # # <option value="$" class="bold">Dollar</option>
+ # # <option value="DKK" onclick="alert('HI');">Kroner</option>
#
# If you wish to specify disabled option tags, set +selected+ to be a hash, with <tt>:disabled</tt> being either a value
# or array of values to be disabled. In this case, you can use <tt>:selected</tt> to specify selected option tags.
#
# Examples:
# options_for_select(["Free", "Basic", "Advanced", "Super Platinum"], :disabled => "Super Platinum")
- # <option value="Free">Free</option>\n<option value="Basic">Basic</option>\n<option value="Advanced">Advanced</option>\n<option value="Super Platinum" disabled="disabled">Super Platinum</option>
+ # # <option value="Free">Free</option>
+ # # <option value="Basic">Basic</option>
+ # # <option value="Advanced">Advanced</option>
+ # # <option value="Super Platinum" disabled="disabled">Super Platinum</option>
#
# options_for_select(["Free", "Basic", "Advanced", "Super Platinum"], :disabled => ["Advanced", "Super Platinum"])
- # <option value="Free">Free</option>\n<option value="Basic">Basic</option>\n<option value="Advanced" disabled="disabled">Advanced</option>\n<option value="Super Platinum" disabled="disabled">Super Platinum</option>
+ # # <option value="Free">Free</option>
+ # # <option value="Basic">Basic</option>
+ # # <option value="Advanced" disabled="disabled">Advanced</option>
+ # # <option value="Super Platinum" disabled="disabled">Super Platinum</option>
#
# options_for_select(["Free", "Basic", "Advanced", "Super Platinum"], :selected => "Free", :disabled => "Super Platinum")
- # <option value="Free" selected="selected">Free</option>\n<option value="Basic">Basic</option>\n<option value="Advanced">Advanced</option>\n<option value="Super Platinum" disabled="disabled">Super Platinum</option>
+ # # <option value="Free" selected="selected">Free</option>
+ # # <option value="Basic">Basic</option>
+ # # <option value="Advanced">Advanced</option>
+ # # <option value="Super Platinum" disabled="disabled">Super Platinum</option>
#
# NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag.
def options_for_select(container, selected = nil)
@@ -45,7 +45,7 @@ module FormTagHelper
# # => <form action="/posts" method="post">
#
# form_tag('/posts/1', :method => :put)
- # # => <form action="/posts/1" method="put">
+ # # => <form action="/posts/1" method="post"> ... <input name="_method" type="hidden" value="put" /> ...
#
# form_tag('/upload', :multipart => true)
# # => <form action="/upload" method="post" enctype="multipart/form-data">
@@ -45,7 +45,7 @@ module TextHelper
# if logged_in
# concat "Logged in!"
# else
- # concat link_to('login', :action => login)
+ # concat link_to('login', :action => :login)
# end
# # will either display "Logged in!" or a login link
# %>
@@ -179,6 +179,9 @@ def test_assert_redirect_to_named_route_failure
assert_redirected_to 'http://test.host/route_two'
end
assert_raise(ActiveSupport::TestCase::Assertion) do
+ assert_redirected_to %r(^http://test.host/route_two)
+ end
+ assert_raise(ActiveSupport::TestCase::Assertion) do
assert_redirected_to :controller => 'action_pack_assertions', :action => 'nothing', :id => 'two'
end
assert_raise(ActiveSupport::TestCase::Assertion) do
@@ -212,6 +215,7 @@ def test_assert_redirected_to_top_level_named_route_from_nested_controller
process :redirect_to_top_level_named_route
# assert_redirected_to "http://test.host/action_pack_assertions/foo" would pass because of exact match early return
assert_redirected_to "/action_pack_assertions/foo"
+ assert_redirected_to %r(/action_pack_assertions/foo)
end
end
Oops, something went wrong. Retry.

0 comments on commit b13849d

Please sign in to comment.