diff options
-rw-r--r-- | actionpack/lib/action_dispatch/routing/mapper.rb | 150 | ||||
-rw-r--r-- | actionview/lib/action_view/helpers/asset_url_helper.rb | 29 | ||||
-rw-r--r-- | activejob/CHANGELOG.md | 5 | ||||
-rw-r--r-- | activejob/lib/active_job/test_helper.rb | 13 | ||||
-rw-r--r-- | activejob/test/cases/test_helper_test.rb | 22 |
5 files changed, 130 insertions, 89 deletions
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index ab13fb14ce..a0d12144c4 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -70,7 +70,7 @@ module ActionDispatch options.delete :shallow_prefix options.delete :shallow - defaults = (scope[:defaults] || {}).merge options.delete(:defaults) || {} + defaults = (scope[:defaults] || {}).dup new scope, set, path, defaults, as, options end @@ -684,7 +684,11 @@ module ActionDispatch def map_method(method, args, &block) options = args.extract_options! options[:via] = method - match(*args, options, &block) + if options.key?(:defaults) + defaults(options.delete(:defaults)) { match(*args, options, &block) } + else + match(*args, options, &block) + end self end end @@ -787,8 +791,8 @@ module ActionDispatch end if options[:constraints].is_a?(Hash) - defaults = options[:constraints].select do - |k, v| URL_OPTIONS.include?(k) && (v.is_a?(String) || v.is_a?(Fixnum)) + defaults = options[:constraints].select do |k, v| + URL_OPTIONS.include?(k) && (v.is_a?(String) || v.is_a?(Fixnum)) end (options[:defaults] ||= {}).reverse_merge!(defaults) @@ -822,9 +826,11 @@ module ActionDispatch # controller "food" do # match "bacon", action: :bacon, via: :get # end - def controller(controller, options={}) - options[:controller] = controller - scope(options) { yield } + def controller(controller) + @scope = @scope.new(controller: controller) + yield + ensure + @scope = @scope.parent end # Scopes routes to a specific namespace. For example: @@ -944,7 +950,10 @@ module ActionDispatch # end # Using this, the +:id+ parameter here will default to 'home'. def defaults(defaults = {}) - scope(:defaults => defaults) { yield } + @scope = @scope.new(defaults: merge_defaults_scope(@scope[:defaults], defaults)) + yield + ensure + @scope = @scope.parent end private @@ -1056,14 +1065,14 @@ module ActionDispatch class Resource #:nodoc: attr_reader :controller, :path, :options, :param - def initialize(entities, api_only = false, options = {}) + def initialize(entities, api_only, shallow, options = {}) @name = entities.to_s @path = (options[:path] || @name).to_s @controller = (options[:controller] || @name).to_s @as = options[:as] @param = (options[:param] || :id).to_sym @options = options - @shallow = false + @shallow = shallow @api_only = api_only end @@ -1129,17 +1138,15 @@ module ActionDispatch "#{path}/:#{nested_param}" end - def shallow=(value) - @shallow = value - end - def shallow? @shallow end + + def singleton?; false; end end class SingletonResource < Resource #:nodoc: - def initialize(entities, api_only, options) + def initialize(entities, api_only, shallow, options) super @as = nil @controller = (options[:controller] || plural).to_s @@ -1167,6 +1174,8 @@ module ActionDispatch alias :member_scope :path alias :nested_scope :path + + def singleton?; true; end end def resources_path_names(options) @@ -1201,20 +1210,22 @@ module ActionDispatch return self end - resource_scope(:resource, SingletonResource.new(resources.pop, api_only?, options)) do - yield if block_given? + with_scope_level(:resource) do + resource_scope(SingletonResource.new(resources.pop, api_only?, @scope[:shallow], options)) do + yield if block_given? - concerns(options[:concerns]) if options[:concerns] + concerns(options[:concerns]) if options[:concerns] - collection do - post :create - end if parent_resource.actions.include?(:create) + collection do + post :create + end if parent_resource.actions.include?(:create) - new do - get :new - end if parent_resource.actions.include?(:new) + new do + get :new + end if parent_resource.actions.include?(:new) - set_member_mappings_for_resource + set_member_mappings_for_resource + end end self @@ -1359,21 +1370,23 @@ module ActionDispatch return self end - resource_scope(:resources, Resource.new(resources.pop, api_only?, options)) do - yield if block_given? + with_scope_level(:resources) do + resource_scope(Resource.new(resources.pop, api_only?, @scope[:shallow], options)) do + yield if block_given? - concerns(options[:concerns]) if options[:concerns] + concerns(options[:concerns]) if options[:concerns] - collection do - get :index if parent_resource.actions.include?(:index) - post :create if parent_resource.actions.include?(:create) - end + collection do + get :index if parent_resource.actions.include?(:index) + post :create if parent_resource.actions.include?(:create) + end - new do - get :new - end if parent_resource.actions.include?(:new) + new do + get :new + end if parent_resource.actions.include?(:new) - set_member_mappings_for_resource + set_member_mappings_for_resource + end end self @@ -1479,7 +1492,7 @@ module ActionDispatch end def shallow? - parent_resource.instance_of?(Resource) && @scope[:shallow] + !parent_resource.singleton? && @scope[:shallow] end # Matches a url pattern to one or more routes. @@ -1591,7 +1604,7 @@ module ActionDispatch if @scope.resources? with_scope_level(:root) do - scope(parent_resource.path) do + path_scope(parent_resource.path) do super(options) end end @@ -1667,18 +1680,6 @@ module ActionDispatch @scope.nested? end - def with_exclusive_scope - begin - @scope = @scope.new(:as => nil, :path => nil) - - with_scope_level(:exclusive) do - yield - end - ensure - @scope = @scope.parent - end - end - def with_scope_level(kind) @scope = @scope.new_level(kind) yield @@ -1686,16 +1687,11 @@ module ActionDispatch @scope = @scope.parent end - def resource_scope(kind, resource) #:nodoc: - resource.shallow = @scope[:shallow] + def resource_scope(resource) #:nodoc: @scope = @scope.new(:scope_level_resource => resource) - @nesting.push(resource) - with_scope_level(kind) do - controller_scope(parent_resource.resource_scope) { yield } - end + controller(resource.resource_scope) { yield } ensure - @nesting.pop @scope = @scope.parent end @@ -1708,12 +1704,10 @@ module ActionDispatch options end - def nesting_depth #:nodoc: - @nesting.size - end - def shallow_nesting_depth #:nodoc: - @nesting.count(&:shallow?) + @scope.find_all { |node| + node.frame[:scope_level_resource] + }.count { |node| node.frame[:scope_level_resource].shallow? } end def param_constraint? #:nodoc: @@ -1806,13 +1800,6 @@ module ActionDispatch end private - def controller_scope(controller) - @scope = @scope.new(controller: controller) - yield - ensure - @scope = @scope.parent - end - def path_scope(path) @scope = @scope.new(path: merge_path_scope(@scope[:path], path)) yield @@ -1936,7 +1923,7 @@ module ActionDispatch attr_reader :parent, :scope_level - def initialize(hash, parent = {}, scope_level = nil) + def initialize(hash, parent = NULL, scope_level = nil) @hash = hash @parent = parent @scope_level = scope_level @@ -1984,23 +1971,34 @@ module ActionDispatch end def new_level(level) - self.class.new(self, self, level) + self.class.new(frame, self, level) end - def fetch(key, &block) - @hash.fetch(key, &block) + def [](key) + scope = find { |node| node.frame.key? key } + scope && scope.frame[key] end - def [](key) - @hash.fetch(key) { @parent[key] } + include Enumerable + + def each + node = self + loop do + break if node.equal? NULL + yield node + node = node.parent + end end + + def frame; @hash; end + + NULL = Scope.new(nil, nil) end def initialize(set) #:nodoc: @set = set @scope = Scope.new({ :path_names => @set.resources_path_names }) @concerns = {} - @nesting = [] end include Base diff --git a/actionview/lib/action_view/helpers/asset_url_helper.rb b/actionview/lib/action_view/helpers/asset_url_helper.rb index 3beb7fefb1..6ac8185b0f 100644 --- a/actionview/lib/action_view/helpers/asset_url_helper.rb +++ b/actionview/lib/action_view/helpers/asset_url_helper.rb @@ -31,26 +31,33 @@ module ActionView # stylesheet_link_tag("application") # # => <link href="http://assets.example.com/assets/application.css" media="screen" rel="stylesheet" /> # - # Browsers typically open at most two simultaneous connections to a single - # host, which means your assets often have to wait for other assets to finish - # downloading. You can alleviate this by using a <tt>%d</tt> wildcard in the - # +asset_host+. For example, "assets%d.example.com". If that wildcard is - # present Rails distributes asset requests among the corresponding four hosts - # "assets0.example.com", ..., "assets3.example.com". With this trick browsers - # will open eight simultaneous connections rather than two. + # Browsers open a limited number of simultaneous connections to a single + # host. The exact number varies by browser and version. This limit may cause + # some asset downloads to wait for previous assets to finish before they can + # begin. You can use the <tt>%d</tt> wildcard in the +asset_host+ to + # distribute the requests over four hosts. For example, + # <tt>assets%d.example.com<tt> will spread the asset requests over + # "assets0.example.com", ..., "assets3.example.com". # # image_tag("rails.png") # # => <img alt="Rails" src="http://assets0.example.com/assets/rails.png" /> # stylesheet_link_tag("application") # # => <link href="http://assets2.example.com/assets/application.css" media="screen" rel="stylesheet" /> # - # To do this, you can either setup four actual hosts, or you can use wildcard - # DNS to CNAME the wildcard to a single asset host. You can read more about - # setting up your DNS CNAME records from your ISP. + # This may improve the asset loading performance of your application. + # It is also possible the combination of additional connection overhead + # (DNS, SSL) and the overall browser connection limits may result in this + # solution being slower. You should be sure to measure your actual + # performance across targeted browers both before and after this change. + # + # To implement the corresponding hosts you can either setup four actual + # hosts or use wildcard DNS to CNAME the wilcard to a single asset host. + # You can read more about setting up your DNS CNAME records from your ISP. # # Note: This is purely a browser performance optimization and is not meant # for server load balancing. See http://www.die.net/musings/page_load_time/ - # for background. + # for background and http://www.browserscope.org/?category=network for + # connection limit data. # # Alternatively, you can exert more control over the asset host by setting # +asset_host+ to a proc like this: diff --git a/activejob/CHANGELOG.md b/activejob/CHANGELOG.md index 1bd97eed38..d8944a5338 100644 --- a/activejob/CHANGELOG.md +++ b/activejob/CHANGELOG.md @@ -1,3 +1,8 @@ +* `assert_enqueued_with` and `assert_performed_with` now returns the matched + job instance for further assertions. + + *Jean Boussier* + * Include I18n.locale into job serialization/deserialization and use it around `perform`. diff --git a/activejob/lib/active_job/test_helper.rb b/activejob/lib/active_job/test_helper.rb index e71a3b4f85..74a12884ff 100644 --- a/activejob/lib/active_job/test_helper.rb +++ b/activejob/lib/active_job/test_helper.rb @@ -233,10 +233,11 @@ module ActiveJob args.assert_valid_keys(:job, :args, :at, :queue) serialized_args = serialize_args_for_assertion(args) yield - matching_job = enqueued_jobs.any? do |job| + matching_job = enqueued_jobs.find do |job| serialized_args.all? { |key, value| value == job[key] } end assert matching_job, "No enqueued job found with #{args}" + instanciate_job(matching_job) ensure queue_adapter.enqueued_jobs = original_enqueued_jobs + enqueued_jobs end @@ -254,10 +255,11 @@ module ActiveJob args.assert_valid_keys(:job, :args, :at, :queue) serialized_args = serialize_args_for_assertion(args) perform_enqueued_jobs { yield } - matching_job = performed_jobs.any? do |job| + matching_job = performed_jobs.find do |job| serialized_args.all? { |key, value| value == job[key] } end assert matching_job, "No performed job found with #{args}" + instanciate_job(matching_job) ensure queue_adapter.performed_jobs = original_performed_jobs + performed_jobs end @@ -311,6 +313,13 @@ module ActiveJob end serialized_args end + + def instanciate_job(payload) + job = payload[:job].new(*payload[:args]) + job.scheduled_at = Time.at(payload[:at]) if payload.key?(:at) + job.queue_name = payload[:queue] + job + end end end end diff --git a/activejob/test/cases/test_helper_test.rb b/activejob/test/cases/test_helper_test.rb index 04c4c446e2..8c60f037d2 100644 --- a/activejob/test/cases/test_helper_test.rb +++ b/activejob/test/cases/test_helper_test.rb @@ -165,6 +165,17 @@ class EnqueuedJobsTest < ActiveJob::TestCase end end + def test_assert_enqueued_job_returns + job = assert_enqueued_with(job: LoggingJob) do + LoggingJob.set(wait_until: 5.minutes.from_now).perform_later(1, 2, 3) + end + + assert_instance_of LoggingJob, job + assert_in_delta 5.minutes.from_now, job.scheduled_at, 1 + assert_equal 'default', job.queue_name + assert_equal [1, 2, 3], job.arguments + end + def test_assert_enqueued_job_failure assert_raise ActiveSupport::TestCase::Assertion do assert_enqueued_with(job: LoggingJob, queue: 'default') do @@ -397,6 +408,17 @@ class PerformedJobsTest < ActiveJob::TestCase end end + def test_assert_performed_job_returns + job = assert_performed_with(job: NestedJob, queue: 'default') do + NestedJob.perform_later + end + + assert_instance_of NestedJob, job + assert_nil job.scheduled_at + assert_equal [], job.arguments + assert_equal 'default', job.queue_name + end + def test_assert_performed_job_failure assert_raise ActiveSupport::TestCase::Assertion do assert_performed_with(job: LoggingJob, at: Date.tomorrow.noon, queue: 'default') do |