aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb150
-rw-r--r--actionview/lib/action_view/helpers/asset_url_helper.rb29
-rw-r--r--activejob/CHANGELOG.md5
-rw-r--r--activejob/lib/active_job/test_helper.rb13
-rw-r--r--activejob/test/cases/test_helper_test.rb22
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