aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile.lock2
-rw-r--r--actionpack/lib/action_controller/caching.rb1
-rw-r--r--actionpack/lib/action_controller/metal/etag_with_template_digest.rb2
-rw-r--r--actionpack/lib/action_controller/test_case.rb8
-rw-r--r--actionpack/lib/action_dispatch/http/cache.rb4
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb12
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb6
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb4
-rw-r--r--actionpack/lib/action_dispatch/middleware/params_parser.rb6
-rw-r--r--actionpack/lib/action_dispatch/middleware/stack.rb4
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb27
-rw-r--r--actionpack/test/abstract_unit.rb94
-rw-r--r--actionpack/test/controller/integration_test.rb266
-rw-r--r--actionpack/test/controller/live_stream_test.rb4
-rw-r--r--actionpack/test/controller/request_forgery_protection_test.rb32
-rw-r--r--actionpack/test/controller/resources_test.rb32
-rw-r--r--actionpack/test/controller/routing_test.rb42
-rw-r--r--actionpack/test/controller/test_case_test.rb2
-rw-r--r--actionpack/test/dispatch/callbacks_test.rb2
-rw-r--r--actionpack/test/dispatch/debug_exceptions_test.rb57
-rw-r--r--actionpack/test/dispatch/live_response_test.rb2
-rw-r--r--actionpack/test/dispatch/routing/inspector_test.rb9
-rw-r--r--actionview/lib/action_view/layouts.rb15
-rw-r--r--actionview/lib/action_view/lookup_context.rb16
-rw-r--r--actionview/lib/action_view/renderer/streaming_template_renderer.rb2
-rw-r--r--actionview/lib/action_view/renderer/template_renderer.rb19
-rw-r--r--activejob/CHANGELOG.md5
-rw-r--r--activejob/Rakefile2
-rw-r--r--activejob/lib/active_job.rb1
-rw-r--r--activejob/lib/active_job/async_job.rb75
-rw-r--r--activejob/lib/active_job/queue_adapters.rb9
-rw-r--r--activejob/lib/active_job/queue_adapters/async_adapter.rb23
-rw-r--r--activejob/test/adapters/async.rb5
-rw-r--r--activejob/test/cases/async_job_test.rb42
-rw-r--r--activejob/test/integration/queuing_test.rb2
-rw-r--r--activejob/test/jobs/queue_as_job.rb10
-rw-r--r--activejob/test/support/integration/adapters/async.rb9
-rw-r--r--activemodel/lib/active_model/serialization.rb8
-rw-r--r--activerecord/lib/active_record/associations.rb6
-rw-r--r--activerecord/lib/active_record/base.rb1
-rw-r--r--activerecord/lib/active_record/enum.rb3
-rw-r--r--activerecord/lib/active_record/migration.rb2
-rw-r--r--activerecord/lib/active_record/migration/command_recorder.rb16
-rw-r--r--activerecord/test/cases/invertible_migration_test.rb33
-rw-r--r--activerecord/test/cases/migration_test.rb2
-rw-r--r--activerecord/test/cases/persistence_test.rb1
-rw-r--r--activerecord/test/cases/readonly_test.rb1
-rw-r--r--activesupport/activesupport.gemspec2
-rw-r--r--activesupport/lib/active_support/core_ext/kernel/reporting.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/strip.rb4
-rw-r--r--activesupport/lib/active_support/deprecation/proxy_wrappers.rb2
-rw-r--r--activesupport/lib/active_support/deprecation/reporting.rb15
-rw-r--r--activesupport/lib/active_support/time_with_zone.rb11
-rw-r--r--guides/source/active_record_migrations.md2
-rw-r--r--guides/source/debugging_rails_applications.md3
-rw-r--r--guides/source/testing.md17
-rw-r--r--railties/CHANGELOG.md4
-rw-r--r--railties/lib/rails/commands/server.rb2
-rw-r--r--railties/test/application/initializers/frameworks_test.rb1
-rw-r--r--railties/test/commands/server_test.rb7
-rw-r--r--railties/test/path_generation_test.rb18
-rw-r--r--tasks/release.rb2
63 files changed, 641 insertions, 379 deletions
diff --git a/Gemfile.lock b/Gemfile.lock
index 7cd4832b3a..4d9f39c3e7 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -118,7 +118,7 @@ PATH
activesupport (= 5.0.0.alpha)
arel (= 7.0.0.alpha)
activesupport (5.0.0.alpha)
- concurrent-ruby (~> 0.9.0)
+ concurrent-ruby (~> 0.9.1)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
method_source
diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb
index a4e4992cfe..2801db0154 100644
--- a/actionpack/lib/action_controller/caching.rb
+++ b/actionpack/lib/action_controller/caching.rb
@@ -1,6 +1,5 @@
require 'fileutils'
require 'uri'
-require 'set'
module ActionController
# \Caching is a cheap way of speeding up slow applications by keeping the result of
diff --git a/actionpack/lib/action_controller/metal/etag_with_template_digest.rb b/actionpack/lib/action_controller/metal/etag_with_template_digest.rb
index f9303efe6c..669cf55bca 100644
--- a/actionpack/lib/action_controller/metal/etag_with_template_digest.rb
+++ b/actionpack/lib/action_controller/metal/etag_with_template_digest.rb
@@ -25,7 +25,7 @@ module ActionController
class_attribute :etag_with_template_digest
self.etag_with_template_digest = true
- ActiveSupport.on_load :action_view, yield: true do |action_view_base|
+ ActiveSupport.on_load :action_view, yield: true do
etag do |options|
determine_template_etag(options) if etag_with_template_digest
end
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index d14483dc72..103986e44a 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -39,10 +39,6 @@ module ActionController
set_header Rack::QUERY_STRING, string
end
- def request_parameters=(params)
- set_header "action_dispatch.request.request_parameters", params
- end
-
def content_type=(type)
set_header 'CONTENT_TYPE', type
end
@@ -102,7 +98,9 @@ module ActionController
set_header 'rack.input', StringIO.new(data)
end
- @env["PATH_INFO"] ||= generated_path
+ get_header("PATH_INFO") do |k|
+ set_header k, generated_path
+ end
path_parameters[:controller] = controller_path
path_parameters[:action] = action
diff --git a/actionpack/lib/action_dispatch/http/cache.rb b/actionpack/lib/action_dispatch/http/cache.rb
index cc1cb3f0f0..be87343b20 100644
--- a/actionpack/lib/action_dispatch/http/cache.rb
+++ b/actionpack/lib/action_dispatch/http/cache.rb
@@ -8,13 +8,13 @@ module ActionDispatch
HTTP_IF_NONE_MATCH = 'HTTP_IF_NONE_MATCH'.freeze
def if_modified_since
- if since = env[HTTP_IF_MODIFIED_SINCE]
+ if since = get_header(HTTP_IF_MODIFIED_SINCE)
Time.rfc2822(since) rescue nil
end
end
def if_none_match
- env[HTTP_IF_NONE_MATCH]
+ get_header HTTP_IF_NONE_MATCH
end
def if_none_match_etags
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 4748a54550..a3c6f015d9 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -35,7 +35,8 @@ module ActionDispatch
HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM
HTTP_NEGOTIATE HTTP_PRAGMA HTTP_CLIENT_IP
HTTP_X_FORWARDED_FOR HTTP_VERSION
- HTTP_X_REQUEST_ID
+ HTTP_X_REQUEST_ID HTTP_X_FORWARDED_HOST
+ SERVER_ADDR
].freeze
ENV_METHODS.each do |env|
@@ -323,7 +324,9 @@ module ActionDispatch
# Override Rack's GET method to support indifferent access
def GET
- @env["action_dispatch.request.query_parameters"] ||= normalize_encode_params(super || {})
+ get_header("action_dispatch.request.query_parameters") do |k|
+ set_header k, normalize_encode_params(super || {})
+ end
rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
raise ActionController::BadRequest.new(:query, e)
end
@@ -331,7 +334,9 @@ module ActionDispatch
# Override Rack's POST method to support indifferent access
def POST
- @env["action_dispatch.request.request_parameters"] ||= normalize_encode_params(super || {})
+ get_header("action_dispatch.request.request_parameters") do
+ self.request_parameters = normalize_encode_params(super || {})
+ end
rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
raise ActionController::BadRequest.new(:request, e)
end
@@ -352,6 +357,7 @@ module ActionDispatch
end
def request_parameters=(params)
+ raise if params.nil?
set_header("action_dispatch.request.request_parameters".freeze, params)
end
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index 6fcf49030b..e413954066 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -229,10 +229,10 @@ module ActionDispatch
# req = Request.new 'HTTP_HOST' => 'example.com:8080'
# req.raw_host_with_port # => "example.com:8080"
def raw_host_with_port
- if forwarded = env["HTTP_X_FORWARDED_HOST"].presence
+ if forwarded = x_forwarded_host.presence
forwarded.split(/,\s?/).last
else
- env['HTTP_HOST'] || "#{env['SERVER_NAME'] || env['SERVER_ADDR']}:#{env['SERVER_PORT']}"
+ get_header('HTTP_HOST') || "#{server_name || server_addr}:#{get_header('SERVER_PORT')}"
end
end
@@ -348,7 +348,7 @@ module ActionDispatch
end
def server_port
- @env['SERVER_PORT'].to_i
+ get_header('SERVER_PORT').to_i
end
# Returns the \domain part of a \host, such as "rubyonrails.org" in "www.rubyonrails.org". You can specify
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index e4c5b0bd29..6d0387cf74 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -1,6 +1,4 @@
require 'active_support/core_ext/hash/keys'
-require 'active_support/core_ext/module/attribute_accessors'
-require 'active_support/core_ext/object/blank'
require 'active_support/key_generator'
require 'active_support/message_verifier'
require 'active_support/json'
@@ -8,7 +6,7 @@ require 'active_support/json'
module ActionDispatch
class Request < Rack::Request
def cookie_jar
- get_header('action_dispatch.cookies'.freeze) do |k|
+ get_header('action_dispatch.cookies'.freeze) do
self.cookie_jar = Cookies::CookieJar.build(self, cookies)
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb
index 402ad778fa..9cde9c9b98 100644
--- a/actionpack/lib/action_dispatch/middleware/params_parser.rb
+++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb
@@ -37,7 +37,9 @@ module ActionDispatch
def call(env)
request = Request.new(env)
- request.request_parameters = parse_formatted_parameters(request, @parsers)
+ parse_formatted_parameters(request, @parsers) do |params|
+ request.request_parameters = params
+ end
@app.call(env)
end
@@ -48,7 +50,7 @@ module ActionDispatch
strategy = parsers.fetch(request.content_mime_type) { return nil }
- strategy.call(request.raw_post)
+ yield strategy.call(request.raw_post)
rescue => e # JSON or Ruby code block errors
logger(request).debug "Error occurred while parsing request parameters.\nContents:\n\n#{request.raw_post}"
diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb
index 0430ce3b9a..90e2ae6802 100644
--- a/actionpack/lib/action_dispatch/middleware/stack.rb
+++ b/actionpack/lib/action_dispatch/middleware/stack.rb
@@ -87,7 +87,7 @@ module ActionDispatch
middlewares.freeze.reverse.inject(app) { |a, e| e.build(a) }
end
- protected
+ private
def assert_index(index, where)
index = get_class index
@@ -96,8 +96,6 @@ module ActionDispatch
i
end
- private
-
def get_class(klass)
if klass.is_a?(String) || klass.is_a?(Symbol)
classcache = ActiveSupport::Dependencies::Reference
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 51bafb539f..c3a9422ceb 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -368,7 +368,7 @@ module ActionDispatch
end
def dispatcher(raise_on_name_error)
- @set.dispatcher raise_on_name_error
+ Routing::RouteSet::Dispatcher.new raise_on_name_error
end
end
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index af6f0de556..4e29476117 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -28,7 +28,7 @@ module ActionDispatch
def serve(req)
params = req.path_parameters
- controller = controller_reference(req) do
+ controller = req.controller_class do
return [404, {'X-Cascade' => 'pass'}, []]
end
dispatch(controller, params[:action], req)
@@ -40,11 +40,6 @@ module ActionDispatch
end
end
- protected
- def controller_reference(req, &block)
- req.controller_class(&block)
- end
-
private
def dispatch(controller, action, req)
@@ -171,9 +166,9 @@ module ActionDispatch
private
def optimized_helper(args)
- params = parameterize_args(args) { |k|
+ params = parameterize_args(args) do
raise_generation_error(args)
- }
+ end
@route.format params
end
@@ -285,7 +280,7 @@ module ActionDispatch
attr_accessor :formatter, :set, :named_routes, :default_scope, :router
attr_accessor :disable_clear_and_finalize, :resources_path_names
- attr_accessor :default_url_options, :dispatcher_class
+ attr_accessor :default_url_options
attr_reader :env_key
alias :routes :set
@@ -328,7 +323,6 @@ module ActionDispatch
@set = Journey::Routes.new
@router = Journey::Router.new @set
@formatter = Journey::Formatter.new self
- @dispatcher_class = Routing::RouteSet::Dispatcher
end
def relative_url_root
@@ -343,6 +337,11 @@ module ActionDispatch
ActionDispatch::Request
end
+ def make_request(env)
+ request_class.new env
+ end
+ private :make_request
+
def draw(&block)
clear! unless @disable_clear_and_finalize
eval_block(block)
@@ -386,10 +385,6 @@ module ActionDispatch
@prepend.each { |blk| eval_block(blk) }
end
- def dispatcher(raise_on_name_error)
- dispatcher_class.new(raise_on_name_error)
- end
-
module MountedHelpers
extend ActiveSupport::Concern
include UrlFor
@@ -700,7 +695,7 @@ module ActionDispatch
end
def call(env)
- req = request_class.new(env)
+ req = make_request(env)
req.path_info = Journey::Router::Utils.normalize_path(req.path_info)
@router.serve(req)
end
@@ -716,7 +711,7 @@ module ActionDispatch
raise ActionController::RoutingError, e.message
end
- req = request_class.new(env)
+ req = make_request(env)
@router.recognize(req) do |route, params|
params.merge!(extras)
params.each do |key, value|
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index 7ea4249e7e..1a61139dfe 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -19,7 +19,6 @@ begin
rescue LoadError
puts "'drb/unix' is not available"
end
-require 'tempfile'
PROCESS_COUNT = (ENV['N'] || 4).to_i
@@ -42,6 +41,8 @@ module Rails
def env
@_env ||= ActiveSupport::StringInquirer.new(ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "test")
end
+
+ def root; end;
end
end
@@ -117,23 +118,38 @@ class ActionDispatch::IntegrationTest < ActiveSupport::TestCase
get ':controller(/:action)'
end
- # Stub Rails dispatcher so it does not get controller references and
- # simply return the controller#action as Rack::Body.
- class StubDispatcher < ::ActionDispatch::Routing::RouteSet::Dispatcher
- protected
- def controller_reference(controller_param)
- controller_param.params[:controller]
+ class DeadEndRoutes < ActionDispatch::Routing::RouteSet
+ # Stub Rails dispatcher so it does not get controller references and
+ # simply return the controller#action as Rack::Body.
+ class NullController
+ def initialize(controller_name)
+ @controller = controller_name
+ @action = nil
+ end
+
+ def action(action_name)
+ @action = action_name
+ self
+ end
+
+ def call(env)
+ [200, {'Content-Type' => 'text/html'}, ["#{@controller}##{@action}"]]
+ end
+ end
+
+ class NullControllerRequest < DelegateClass(ActionDispatch::Request)
+ def controller_class
+ NullController.new params[:controller]
+ end
end
- def dispatch(controller, action, env)
- [200, {'Content-Type' => 'text/html'}, ["#{controller}##{action}"]]
+ def make_request env
+ NullControllerRequest.new super
end
end
- def self.stub_controllers(config = nil)
- route_set = ActionDispatch::Routing::RouteSet.new(*[config].compact)
- route_set.dispatcher_class = StubDispatcher
- yield route_set
+ def self.stub_controllers(config = ActionDispatch::Routing::RouteSet::DEFAULT_CONFIG)
+ yield DeadEndRoutes.new(config)
end
def with_routing(&block)
@@ -323,39 +339,37 @@ module RoutingTestHelpers
end
class TestSet < ActionDispatch::Routing::RouteSet
- attr_reader :strict
-
- def initialize(block, strict = false)
- @block = block
- @strict = strict
- super()
- end
-
- class Dispatcher < ActionDispatch::Routing::RouteSet::Dispatcher
- def initialize(defaults, set, block)
- super(defaults)
+ class Request < DelegateClass(ActionDispatch::Request)
+ def initialize(target, helpers, block, strict)
+ super(target)
+ @helpers = helpers
@block = block
- @set = set
- end
-
- def controller(params, default_controller=true)
- super(params, @set.strict)
+ @strict = strict
end
- def controller_reference(controller_param)
+ def controller_class
+ helpers = @helpers
block = @block
- set = @set
- super if @set.strict
- Class.new(ActionController::Base) {
- include set.url_helpers
+ Class.new(@strict ? super : ActionController::Base) {
+ include helpers
define_method(:process) { |name| block.call(self) }
def to_a; [200, {}, []]; end
}
end
end
- def dispatcher defaults
- TestSet::Dispatcher.new defaults, self, @block
+ attr_reader :strict
+
+ def initialize(block, strict = false)
+ @block = block
+ @strict = strict
+ super()
+ end
+
+ private
+
+ def make_request(env)
+ Request.new super, url_helpers, @block, strict
end
end
end
@@ -369,13 +383,11 @@ class ThreadsController < ResourcesController; end
class MessagesController < ResourcesController; end
class CommentsController < ResourcesController; end
class ReviewsController < ResourcesController; end
-class LogosController < ResourcesController; end
class AccountsController < ResourcesController; end
class AdminController < ResourcesController; end
class ProductsController < ResourcesController; end
class ImagesController < ResourcesController; end
-class PreferencesController < ResourcesController; end
module Backoffice
class ProductsController < ResourcesController; end
@@ -397,7 +409,7 @@ def jruby_skip(message = '')
end
require 'mocha/setup' # FIXME: stop using mocha
-require 'minitest/mock'
+require 'active_support/testing/method_call_assertions'
class ForkingExecutor
class Server
@@ -469,3 +481,7 @@ if RUBY_ENGINE == "ruby" && PROCESS_COUNT > 0
# Use N processes (N defaults to 4)
Minitest.parallel_executor = ForkingExecutor.new(PROCESS_COUNT)
end
+
+class ActiveSupport::TestCase
+ include ActiveSupport::Testing::MethodCallAssertions
+end
diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb
index dc4c32b07e..de7e800ac1 100644
--- a/actionpack/test/controller/integration_test.rb
+++ b/actionpack/test/controller/integration_test.rb
@@ -26,289 +26,335 @@ class SessionTest < ActiveSupport::TestCase
end
def test_follow_redirect_raises_when_no_redirect
- @session.stubs(:redirect?).returns(false)
- assert_raise(RuntimeError) { @session.follow_redirect! }
+ @session.stub :redirect?, false do
+ assert_raise(RuntimeError) { @session.follow_redirect! }
+ end
end
def test_request_via_redirect_uses_given_method
path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue"}
- @session.expects(:process).with(:put, path, params: args, headers: headers)
- @session.stubs(:redirect?).returns(false)
- @session.request_via_redirect(:put, path, params: args, headers: headers)
+ assert_called_with @session, :process, [:put, path, params: args, headers: headers] do
+ @session.stub :redirect?, false do
+ @session.request_via_redirect(:put, path, params: args, headers: headers)
+ end
+ end
end
def test_deprecated_request_via_redirect_uses_given_method
path = "/somepath"; args = { id: '1' }; headers = { "X-Test-Header" => "testvalue" }
- @session.expects(:process).with(:put, path, params: args, headers: headers)
- @session.stubs(:redirect?).returns(false)
- assert_deprecated { @session.request_via_redirect(:put, path, args, headers) }
+ assert_called_with @session, :process, [:put, path, params: args, headers: headers] do
+ @session.stub :redirect?, false do
+ assert_deprecated { @session.request_via_redirect(:put, path, args, headers) }
+ end
+ end
end
def test_request_via_redirect_follows_redirects
path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue"}
- @session.stubs(:redirect?).returns(true, true, false)
- @session.expects(:follow_redirect!).times(2)
- @session.request_via_redirect(:get, path, params: args, headers: headers)
+ value_series = [true, true, false]
+ assert_called @session, :follow_redirect!, times: 2 do
+ @session.stub :redirect?, ->{ value_series.shift } do
+ @session.request_via_redirect(:get, path, params: args, headers: headers)
+ end
+ end
end
def test_request_via_redirect_returns_status
path = "/somepath"; args = {:id => '1'}; headers = {"X-Test-Header" => "testvalue"}
- @session.stubs(:redirect?).returns(false)
- @session.stubs(:status).returns(200)
- assert_equal 200, @session.request_via_redirect(:get, path, params: args, headers: headers)
+ @session.stub :redirect?, false do
+ @session.stub :status, 200 do
+ assert_equal 200, @session.request_via_redirect(:get, path, params: args, headers: headers)
+ end
+ end
end
def test_deprecated_get_via_redirect
path = "/somepath"; args = { id: '1' }; headers = { "X-Test-Header" => "testvalue" }
- @session.expects(:request_via_redirect).with(:get, path, args, headers)
- assert_deprecated do
- @session.get_via_redirect(path, args, headers)
+ assert_called_with @session, :request_via_redirect, [:get, path, args, headers] do
+ assert_deprecated do
+ @session.get_via_redirect(path, args, headers)
+ end
end
end
def test_deprecated_post_via_redirect
path = "/somepath"; args = { id: '1' }; headers = { "X-Test-Header" => "testvalue" }
- @session.expects(:request_via_redirect).with(:post, path, args, headers)
- assert_deprecated do
- @session.post_via_redirect(path, args, headers)
+ assert_called_with @session, :request_via_redirect, [:post, path, args, headers] do
+ assert_deprecated do
+ @session.post_via_redirect(path, args, headers)
+ end
end
end
def test_deprecated_patch_via_redirect
path = "/somepath"; args = { id: '1' }; headers = { "X-Test-Header" => "testvalue" }
- @session.expects(:request_via_redirect).with(:patch, path, args, headers)
- assert_deprecated do
- @session.patch_via_redirect(path, args, headers)
+ assert_called_with @session, :request_via_redirect, [:patch, path, args, headers] do
+ assert_deprecated do
+ @session.patch_via_redirect(path, args, headers)
+ end
end
end
def test_deprecated_put_via_redirect
path = "/somepath"; args = { id: '1' }; headers = { "X-Test-Header" => "testvalue" }
- @session.expects(:request_via_redirect).with(:put, path, args, headers)
- assert_deprecated do
- @session.put_via_redirect(path, args, headers)
+ assert_called_with @session, :request_via_redirect, [:put, path, args, headers] do
+ assert_deprecated do
+ @session.put_via_redirect(path, args, headers)
+ end
end
end
def test_deprecated_delete_via_redirect
path = "/somepath"; args = { id: '1' }; headers = { "X-Test-Header" => "testvalue" }
- @session.expects(:request_via_redirect).with(:delete, path, args, headers)
- assert_deprecated do
- @session.delete_via_redirect(path, args, headers)
+ assert_called_with @session, :request_via_redirect, [:delete, path, args, headers] do
+ assert_deprecated do
+ @session.delete_via_redirect(path, args, headers)
+ end
end
end
def test_get
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:get, path, params: params, headers: headers)
- @session.get(path, params: params, headers: headers)
+
+ assert_called_with @session, :process, [:get, path, params: params, headers: headers] do
+ @session.get(path, params: params, headers: headers)
+ end
end
def test_get_with_env_and_headers
path = "/index"; params = "blah"; headers = { location: 'blah' }; env = { 'HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest' }
- @session.expects(:process).with(:get, path, params: params, headers: headers, env: env)
- @session.get(path, params: params, headers: headers, env: env)
+ assert_called_with @session, :process, [:get, path, params: params, headers: headers, env: env] do
+ @session.get(path, params: params, headers: headers, env: env)
+ end
end
def test_deprecated_get
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:get, path, params: params, headers: headers)
- assert_deprecated {
- @session.get(path, params, headers)
- }
+
+ assert_called_with @session, :process, [:get, path, params: params, headers: headers] do
+ assert_deprecated {
+ @session.get(path, params, headers)
+ }
+ end
end
def test_post
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:post, path, params: params, headers: headers)
- assert_deprecated {
- @session.post(path, params, headers)
- }
+ assert_called_with @session, :process, [:post, path, params: params, headers: headers] do
+ assert_deprecated {
+ @session.post(path, params, headers)
+ }
+ end
end
def test_deprecated_post
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:post, path, params: params, headers: headers)
- @session.post(path, params: params, headers: headers)
+ assert_called_with @session, :process, [:post, path, params: params, headers: headers] do
+ @session.post(path, params: params, headers: headers)
+ end
end
def test_patch
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:patch, path, params: params, headers: headers)
- @session.patch(path, params: params, headers: headers)
+ assert_called_with @session, :process, [:patch, path, params: params, headers: headers] do
+ @session.patch(path, params: params, headers: headers)
+ end
end
def test_deprecated_patch
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:patch, path, params: params, headers: headers)
- assert_deprecated {
- @session.patch(path, params, headers)
- }
+ assert_called_with @session, :process, [:patch, path, params: params, headers: headers] do
+ assert_deprecated {
+ @session.patch(path, params, headers)
+ }
+ end
end
def test_put
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:put, path, params: params, headers: headers)
- @session.put(path, params: params, headers: headers)
+ assert_called_with @session, :process, [:put, path, params: params, headers: headers] do
+ @session.put(path, params: params, headers: headers)
+ end
end
def test_deprecated_put
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:put, path, params: params, headers: headers)
- assert_deprecated {
- @session.put(path, params, headers)
- }
+ assert_called_with @session, :process, [:put, path, params: params, headers: headers] do
+ assert_deprecated {
+ @session.put(path, params, headers)
+ }
+ end
end
def test_delete
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:delete, path, params: params, headers: headers)
- assert_deprecated {
- @session.delete(path,params,headers)
- }
+ assert_called_with @session, :process, [:delete, path, params: params, headers: headers] do
+ assert_deprecated {
+ @session.delete(path,params,headers)
+ }
+ end
end
def test_deprecated_delete
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:delete, path, params: params, headers: headers)
- @session.delete(path, params: params, headers: headers)
+ assert_called_with @session, :process, [:delete, path, params: params, headers: headers] do
+ @session.delete(path, params: params, headers: headers)
+ end
end
def test_head
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:head, path, params: params, headers: headers)
- @session.head(path, params: params, headers: headers)
+ assert_called_with @session, :process, [:head, path, params: params, headers: headers] do
+ @session.head(path, params: params, headers: headers)
+ end
end
def deprecated_test_head
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:head, path, params: params, headers: headers)
- assert_deprecated {
- @session.head(path, params, headers)
- }
+ assert_called_with @session, :process, [:head, path, params: params, headers: headers] do
+ assert_deprecated {
+ @session.head(path, params, headers)
+ }
+ end
end
def test_xml_http_request_get
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:get, path, params: params, headers: headers, xhr: true)
- @session.get(path, params: params, headers: headers, xhr: true)
+ assert_called_with @session, :process, [:get, path, params: params, headers: headers, xhr: true] do
+ @session.get(path, params: params, headers: headers, xhr: true)
+ end
end
def test_deprecated_xml_http_request_get
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:get, path, params: params, headers: headers, xhr: true)
- @session.get(path, params: params, headers: headers, xhr: true)
+ assert_called_with @session, :process, [:get, path, params: params, headers: headers, xhr: true] do
+ @session.get(path, params: params, headers: headers, xhr: true)
+ end
end
def test_deprecated_args_xml_http_request_get
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:get, path, params: params, headers: headers, xhr: true)
- assert_deprecated(/xml_http_request/) {
- @session.xml_http_request(:get, path, params, headers)
- }
+ assert_called_with @session, :process, [:get, path, params: params, headers: headers, xhr: true] do
+ assert_deprecated(/xml_http_request/) {
+ @session.xml_http_request(:get, path, params, headers)
+ }
+ end
end
def test_xml_http_request_post
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:post, path, params: params, headers: headers, xhr: true)
- @session.post(path, params: params, headers: headers, xhr: true)
+ assert_called_with @session, :process, [:post, path, params: params, headers: headers, xhr: true] do
+ @session.post(path, params: params, headers: headers, xhr: true)
+ end
end
def test_deprecated_xml_http_request_post
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:post, path, params: params, headers: headers, xhr: true)
- @session.post(path, params: params, headers: headers, xhr: true)
+ assert_called_with @session, :process, [:post, path, params: params, headers: headers, xhr: true] do
+ @session.post(path, params: params, headers: headers, xhr: true)
+ end
end
def test_deprecated_args_xml_http_request_post
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:post, path, params: params, headers: headers, xhr: true)
- assert_deprecated(/xml_http_request/) { @session.xml_http_request(:post,path,params,headers) }
+ assert_called_with @session, :process, [:post, path, params: params, headers: headers, xhr: true] do
+ assert_deprecated(/xml_http_request/) { @session.xml_http_request(:post,path,params,headers) }
+ end
end
def test_xml_http_request_patch
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:patch, path, params: params, headers: headers, xhr: true)
- @session.patch(path, params: params, headers: headers, xhr: true)
+ assert_called_with @session, :process, [:patch, path, params: params, headers: headers, xhr: true] do
+ @session.patch(path, params: params, headers: headers, xhr: true)
+ end
end
def test_deprecated_xml_http_request_patch
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:patch, path, params: params, headers: headers, xhr: true)
- @session.patch(path, params: params, headers: headers, xhr: true)
+ assert_called_with @session, :process, [:patch, path, params: params, headers: headers, xhr: true] do
+ @session.patch(path, params: params, headers: headers, xhr: true)
+ end
end
def test_deprecated_args_xml_http_request_patch
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:patch, path, params: params, headers: headers, xhr: true)
- assert_deprecated(/xml_http_request/) { @session.xml_http_request(:patch,path,params,headers) }
+ assert_called_with @session, :process, [:patch, path, params: params, headers: headers, xhr: true] do
+ assert_deprecated(/xml_http_request/) { @session.xml_http_request(:patch,path,params,headers) }
+ end
end
def test_xml_http_request_put
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:put, path, params: params, headers: headers, xhr: true)
- @session.put(path, params: params, headers: headers, xhr: true)
+ assert_called_with @session, :process, [:put, path, params: params, headers: headers, xhr: true] do
+ @session.put(path, params: params, headers: headers, xhr: true)
+ end
end
def test_deprecated_xml_http_request_put
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:put, path, params: params, headers: headers, xhr: true)
- @session.put(path, params: params, headers: headers, xhr: true)
+ assert_called_with @session, :process, [:put, path, params: params, headers: headers, xhr: true] do
+ @session.put(path, params: params, headers: headers, xhr: true)
+ end
end
def test_deprecated_args_xml_http_request_put
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:put, path, params: params, headers: headers, xhr: true)
- assert_deprecated(/xml_http_request/) { @session.xml_http_request(:put, path, params, headers) }
+ assert_called_with @session, :process, [:put, path, params: params, headers: headers, xhr: true] do
+ assert_deprecated(/xml_http_request/) { @session.xml_http_request(:put, path, params, headers) }
+ end
end
def test_xml_http_request_delete
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:delete, path, params: params, headers: headers, xhr: true)
- @session.delete(path, params: params, headers: headers, xhr: true)
+ assert_called_with @session, :process, [:delete, path, params: params, headers: headers, xhr: true] do
+ @session.delete(path, params: params, headers: headers, xhr: true)
+ end
end
def test_deprecated_xml_http_request_delete
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:delete, path, params: params, headers: headers, xhr: true)
- assert_deprecated { @session.xml_http_request(:delete, path, params: params, headers: headers) }
+ assert_called_with @session, :process, [:delete, path, params: params, headers: headers, xhr: true] do
+ assert_deprecated { @session.xml_http_request(:delete, path, params: params, headers: headers) }
+ end
end
def test_deprecated_args_xml_http_request_delete
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:delete, path, params: params, headers: headers, xhr: true)
- assert_deprecated(/xml_http_request/) { @session.xml_http_request(:delete, path, params, headers) }
+ assert_called_with @session, :process, [:delete, path, params: params, headers: headers, xhr: true] do
+ assert_deprecated(/xml_http_request/) { @session.xml_http_request(:delete, path, params, headers) }
+ end
end
def test_xml_http_request_head
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:head, path, params: params, headers: headers, xhr: true)
- @session.head(path, params: params, headers: headers, xhr: true)
+ assert_called_with @session, :process, [:head, path, params: params, headers: headers, xhr: true] do
+ @session.head(path, params: params, headers: headers, xhr: true)
+ end
end
def test_deprecated_xml_http_request_head
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:head, path, params: params, headers: headers, xhr: true)
- assert_deprecated(/xml_http_request/) { @session.xml_http_request(:head, path, params: params, headers: headers) }
+ assert_called_with @session, :process, [:head, path, params: params, headers: headers, xhr: true] do
+ assert_deprecated(/xml_http_request/) { @session.xml_http_request(:head, path, params: params, headers: headers) }
+ end
end
def test_deprecated_args_xml_http_request_head
path = "/index"; params = "blah"; headers = { location: 'blah' }
- @session.expects(:process).with(:head, path, params: params, headers: headers, xhr: true)
- assert_deprecated { @session.xml_http_request(:head, path, params, headers) }
+ assert_called_with @session, :process, [:head, path, params: params, headers: headers, xhr: true] do
+ assert_deprecated { @session.xml_http_request(:head, path, params, headers) }
+ end
end
end
class IntegrationTestTest < ActiveSupport::TestCase
def setup
@test = ::ActionDispatch::IntegrationTest.new(:app)
- @test.class.stubs(:fixture_table_names).returns([])
- @session = @test.open_session
end
def test_opens_new_session
@@ -340,14 +386,8 @@ end
# Tests that integration tests don't call Controller test methods for processing.
# Integration tests have their own setup and teardown.
class IntegrationTestUsesCorrectClass < ActionDispatch::IntegrationTest
- def self.fixture_table_names
- []
- end
-
def test_integration_methods_called
reset!
- @integration_session.stubs(:generic_url_rewriter)
- @integration_session.stubs(:process)
%w( get post head patch put delete ).each do |verb|
assert_nothing_raised("'#{verb}' should use integration test methods") { __send__(verb, '/') }
diff --git a/actionpack/test/controller/live_stream_test.rb b/actionpack/test/controller/live_stream_test.rb
index 6ba361f2f7..e9c19b7acf 100644
--- a/actionpack/test/controller/live_stream_test.rb
+++ b/actionpack/test/controller/live_stream_test.rb
@@ -315,7 +315,7 @@ module ActionController
t = Thread.new(@response) { |resp|
resp.await_commit
_, _, body = resp.to_a
- body.each do |part|
+ body.each do
@controller.latch.wait
body.close
break
@@ -339,7 +339,7 @@ module ActionController
t = Thread.new(@response) { |resp|
resp.await_commit
_, _, body = resp.to_a
- body.each do |part|
+ body.each do
body.close
break
end
diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb
index f3b0ecac10..90fd8669c2 100644
--- a/actionpack/test/controller/request_forgery_protection_test.rb
+++ b/actionpack/test/controller/request_forgery_protection_test.rb
@@ -131,9 +131,7 @@ end
# common test methods
module RequestForgeryProtectionTests
def setup
- @token = "cf50faa3fe97702ca1ae"
- @controller.stubs(:valid_authenticity_token?).with{ |_, t| t == @token }.returns(true)
- @controller.stubs(:valid_authenticity_token?).with{ |_, t| t != @token }.returns(false)
+ @token = Base64.strict_encode64('railstestrailstestrailstestrails')
@old_request_forgery_protection_token = ActionController::Base.request_forgery_protection_token
ActionController::Base.request_forgery_protection_token = :custom_authenticity_token
end
@@ -255,37 +253,53 @@ module RequestForgeryProtectionTests
end
def test_should_allow_post_with_token
- assert_not_blocked { post :index, params: { custom_authenticity_token: @token } }
+ session[:_csrf_token] = @token
+ @controller.stub :form_authenticity_token, @token do
+ assert_not_blocked { post :index, params: { custom_authenticity_token: @token } }
+ end
end
def test_should_allow_patch_with_token
- assert_not_blocked { patch :index, params: { custom_authenticity_token: @token } }
+ session[:_csrf_token] = @token
+ @controller.stub :form_authenticity_token, @token do
+ assert_not_blocked { patch :index, params: { custom_authenticity_token: @token } }
+ end
end
def test_should_allow_put_with_token
- assert_not_blocked { put :index, params: { custom_authenticity_token: @token } }
+ session[:_csrf_token] = @token
+ @controller.stub :form_authenticity_token, @token do
+ assert_not_blocked { put :index, params: { custom_authenticity_token: @token } }
+ end
end
def test_should_allow_delete_with_token
- assert_not_blocked { delete :index, params: { custom_authenticity_token: @token } }
+ session[:_csrf_token] = @token
+ @controller.stub :form_authenticity_token, @token do
+ assert_not_blocked { delete :index, params: { custom_authenticity_token: @token } }
+ end
end
def test_should_allow_post_with_token_in_header
+ session[:_csrf_token] = @token
@request.env['HTTP_X_CSRF_TOKEN'] = @token
assert_not_blocked { post :index }
end
def test_should_allow_delete_with_token_in_header
+ session[:_csrf_token] = @token
@request.env['HTTP_X_CSRF_TOKEN'] = @token
assert_not_blocked { delete :index }
end
def test_should_allow_patch_with_token_in_header
+ session[:_csrf_token] = @token
@request.env['HTTP_X_CSRF_TOKEN'] = @token
assert_not_blocked { patch :index }
end
def test_should_allow_put_with_token_in_header
+ session[:_csrf_token] = @token
@request.env['HTTP_X_CSRF_TOKEN'] = @token
assert_not_blocked { put :index }
end
@@ -339,6 +353,7 @@ module RequestForgeryProtectionTests
# Allow non-GET requests since GET is all a remote <script> tag can muster.
def test_should_allow_non_get_js_without_xhr_header
+ session[:_csrf_token] = @token
assert_cross_origin_not_blocked { post :same_origin_js, params: { custom_authenticity_token: @token } }
assert_cross_origin_not_blocked { post :same_origin_js, params: { format: 'js', custom_authenticity_token: @token } }
assert_cross_origin_not_blocked do
@@ -412,7 +427,8 @@ class RequestForgeryProtectionControllerUsingResetSessionTest < ActionController
get :meta
assert_select 'meta[name=?][content=?]', 'csrf-param', 'custom_authenticity_token'
assert_select 'meta[name=?]', 'csrf-token'
- assert_match(/cf50faa3fe97702ca1ae&lt;=\?/, @response.body)
+ regexp = "#{@token}&lt;=\?"
+ assert_match(/#{regexp}/, @response.body)
end
end
end
diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb
index dd7c128566..4490abf7b2 100644
--- a/actionpack/test/controller/resources_test.rb
+++ b/actionpack/test/controller/resources_test.rb
@@ -149,7 +149,7 @@ class ResourcesTest < ActionController::TestCase
end
end
- assert_restful_named_routes_for :messages do |options|
+ assert_restful_named_routes_for :messages do
actions.each_key do |action|
assert_named_route "/messages/#{action}", "#{action}_messages_path", :action => action
end
@@ -179,7 +179,7 @@ class ResourcesTest < ActionController::TestCase
end
end
- assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options|
+ assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do
actions.each_key do |action|
assert_named_route "/threads/1/messages/#{action}", "#{action}_thread_messages_path", :action => action
end
@@ -206,7 +206,7 @@ class ResourcesTest < ActionController::TestCase
end
end
- assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options|
+ assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do
actions.each_key do |action|
assert_named_route "/threads/1/messages/#{action}", "#{action}_thread_messages_path", :action => action
end
@@ -236,7 +236,7 @@ class ResourcesTest < ActionController::TestCase
end
end
- assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options|
+ assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do
actions.each_key do |action|
assert_named_route "/threads/1/messages/#{action}.xml", "#{action}_thread_messages_path", :action => action, :format => 'xml'
end
@@ -253,7 +253,7 @@ class ResourcesTest < ActionController::TestCase
assert_recognizes(options.merge(mark_options), :path => mark_path, :method => method)
end
- assert_restful_named_routes_for :messages do |options|
+ assert_restful_named_routes_for :messages do
assert_named_route mark_path, :mark_message_path, mark_options
end
end
@@ -278,7 +278,7 @@ class ResourcesTest < ActionController::TestCase
assert_recognizes(options.merge(mark_options), :path => mark_path, :method => method)
end
- assert_restful_named_routes_for :messages, :path_names => {:new => 'nuevo'} do |options|
+ assert_restful_named_routes_for :messages, :path_names => {:new => 'nuevo'} do
assert_named_route mark_path, :mark_message_path, mark_options
end
end
@@ -304,7 +304,7 @@ class ResourcesTest < ActionController::TestCase
assert_recognizes(options.merge(action_options), :path => action_path, :method => method)
end
- assert_restful_named_routes_for :messages do |options|
+ assert_restful_named_routes_for :messages do
assert_named_route action_path, "#{action}_message_path".to_sym, action_options
end
end
@@ -351,7 +351,7 @@ class ResourcesTest < ActionController::TestCase
assert_recognizes(options.merge(preview_options), :path => preview_path, :method => :post)
end
- assert_restful_named_routes_for :messages do |options|
+ assert_restful_named_routes_for :messages do
assert_named_route preview_path, :preview_new_message_path, preview_options
end
end
@@ -373,7 +373,7 @@ class ResourcesTest < ActionController::TestCase
assert_recognizes(options.merge(preview_options), :path => preview_path, :method => :post)
end
- assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options|
+ assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do
assert_named_route preview_path, :preview_new_thread_message_path, preview_options
end
end
@@ -395,7 +395,7 @@ class ResourcesTest < ActionController::TestCase
assert_recognizes(options.merge(preview_options), :path => preview_path, :method => :post)
end
- assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do |options|
+ assert_restful_named_routes_for :messages, :path_prefix => 'threads/1/', :name_prefix => 'thread_', :options => { :thread_id => '1' } do
assert_named_route preview_path, :preview_new_thread_message_path, preview_options
end
end
@@ -519,9 +519,9 @@ class ResourcesTest < ActionController::TestCase
end
def test_should_create_multiple_singleton_resource_routes
- with_singleton_resources :account, :logo do
+ with_singleton_resources :account, :product do
assert_singleton_restful_for :account
- assert_singleton_restful_for :logo
+ assert_singleton_restful_for :product
end
end
@@ -553,7 +553,7 @@ class ResourcesTest < ActionController::TestCase
assert_recognizes(options.merge(reset_options), :path => reset_path, :method => method)
end
- assert_singleton_named_routes_for :account do |options|
+ assert_singleton_named_routes_for :account do
assert_named_route reset_path, :reset_account_path, reset_options
end
end
@@ -577,7 +577,7 @@ class ResourcesTest < ActionController::TestCase
assert_recognizes(options.merge(action_options), :path => action_path, :method => method)
end
- assert_singleton_named_routes_for :account do |options|
+ assert_singleton_named_routes_for :account do
assert_named_route action_path, "#{action}_account_path".to_sym, action_options
end
end
@@ -1070,8 +1070,8 @@ class ResourcesTest < ActionController::TestCase
end
def test_singleton_resource_name_is_not_singularized
- with_singleton_resources(:preferences) do
- assert_singleton_restful_for :preferences
+ with_singleton_resources(:products) do
+ assert_singleton_restful_for :products
end
end
diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb
index feb3e7eab7..4a2b02a003 100644
--- a/actionpack/test/controller/routing_test.rb
+++ b/actionpack/test/controller/routing_test.rb
@@ -336,6 +336,16 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
assert_equal({controller: 'content', action: 'translate', url: 'example'}, rs.recognize_path('/example'))
end
+ def test_route_with_regexp_for_action
+ rs.draw { get '/:controller/:action', action: /auth[-|_].+/ }
+
+ assert_equal({ action: 'auth_google', controller: 'content' }, rs.recognize_path('/content/auth_google'))
+ assert_equal({ action: 'auth-facebook', controller: 'content' }, rs.recognize_path('/content/auth-facebook'))
+
+ assert_equal '/content/auth_google', url_for(rs, { controller: "content", action: "auth_google" })
+ assert_equal '/content/auth-facebook', url_for(rs, { controller: "content", action: "auth-facebook" })
+ end
+
def test_route_with_regexp_for_controller
rs.draw do
get ':controller/:admintoken(/:action(/:id))', :controller => /admin\/.+/
@@ -1742,40 +1752,10 @@ class RouteSetTest < ActiveSupport::TestCase
include ActionDispatch::RoutingVerbs
- class TestSet < ActionDispatch::Routing::RouteSet
- def initialize(block)
- @block = block
- super()
- end
-
- class Dispatcher < ActionDispatch::Routing::RouteSet::Dispatcher
- def initialize(defaults, set, block)
- super(defaults)
- @block = block
- @set = set
- end
-
- def controller_reference(controller_param)
- block = @block
- set = @set
- Class.new(ActionController::Base) {
- include set.url_helpers
- define_method(:process) { |name| block.call(self) }
- def to_a; [200, {}, []]; end
- }
- end
- end
-
- def dispatcher defaults
- TestSet::Dispatcher.new defaults, self, @block
- end
- end
-
alias :routes :set
def test_generate_with_optional_params_recalls_last_request
- controller = nil
- @set = TestSet.new ->(c) { controller = c }
+ @set = make_set false
set.draw do
get "blog/", :controller => "blog", :action => "index"
diff --git a/actionpack/test/controller/test_case_test.rb b/actionpack/test/controller/test_case_test.rb
index 1f073b4124..b3c3979c84 100644
--- a/actionpack/test/controller/test_case_test.rb
+++ b/actionpack/test/controller/test_case_test.rb
@@ -160,7 +160,7 @@ XML
def setup
super
@controller = TestController.new
- @request.env['PATH_INFO'] = nil
+ @request.delete_header 'PATH_INFO'
@routes = ActionDispatch::Routing::RouteSet.new.tap do |r|
r.draw do
get ':controller(/:action(/:id))'
diff --git a/actionpack/test/dispatch/callbacks_test.rb b/actionpack/test/dispatch/callbacks_test.rb
index f767b07e75..5ba76d9ab9 100644
--- a/actionpack/test/dispatch/callbacks_test.rb
+++ b/actionpack/test/dispatch/callbacks_test.rb
@@ -28,7 +28,7 @@ class DispatcherTest < ActiveSupport::TestCase
assert_equal 4, Foo.a
assert_equal 4, Foo.b
- dispatch do |env|
+ dispatch do
raise "error"
end rescue nil
assert_equal 6, Foo.a
diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb
index a867aee7ec..f9f379780c 100644
--- a/actionpack/test/dispatch/debug_exceptions_test.rb
+++ b/actionpack/test/dispatch/debug_exceptions_test.rb
@@ -71,14 +71,6 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
end
end
- def setup
- app = ActiveSupport::OrderedOptions.new
- app.config = ActiveSupport::OrderedOptions.new
- app.config.assets = ActiveSupport::OrderedOptions.new
- app.config.assets.prefix = '/sprockets'
- Rails.stubs(:application).returns(app)
- end
-
RoutesApp = Struct.new(:routes).new(SharedTestRoutes)
ProductionApp = ActionDispatch::DebugExceptions.new(Boomer.new(false), RoutesApp)
DevelopmentApp = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp)
@@ -338,36 +330,37 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
test 'debug exceptions app shows user code that caused the error in source view' do
@app = DevelopmentApp
- Rails.stubs(:root).returns(Pathname.new('.'))
- cleaner = ActiveSupport::BacktraceCleaner.new.tap do |bc|
- bc.add_silencer { |line| line =~ /method_that_raises/ }
- bc.add_silencer { |line| line !~ %r{test/dispatch/debug_exceptions_test.rb} }
- end
+ Rails.stub :root, Pathname.new('.') do
+ cleaner = ActiveSupport::BacktraceCleaner.new.tap do |bc|
+ bc.add_silencer { |line| line =~ /method_that_raises/ }
+ bc.add_silencer { |line| line !~ %r{test/dispatch/debug_exceptions_test.rb} }
+ end
- get '/framework_raises', headers: { 'action_dispatch.backtrace_cleaner' => cleaner }
+ get '/framework_raises', headers: { 'action_dispatch.backtrace_cleaner' => cleaner }
- # Assert correct error
- assert_response 500
- assert_select 'h2', /error in framework/
+ # Assert correct error
+ assert_response 500
+ assert_select 'h2', /error in framework/
- # assert source view line is the call to method_that_raises
- assert_select 'div.source:not(.hidden)' do
- assert_select 'pre .line.active', /method_that_raises/
- end
+ # assert source view line is the call to method_that_raises
+ assert_select 'div.source:not(.hidden)' do
+ assert_select 'pre .line.active', /method_that_raises/
+ end
- # assert first source view (hidden) that throws the error
- assert_select 'div.source:first' do
- assert_select 'pre .line.active', /raise StandardError\.new/
- end
+ # assert first source view (hidden) that throws the error
+ assert_select 'div.source:first' do
+ assert_select 'pre .line.active', /raise StandardError\.new/
+ end
- # assert application trace refers to line that calls method_that_raises is first
- assert_select '#Application-Trace' do
- assert_select 'pre code a:first', %r{test/dispatch/debug_exceptions_test\.rb:\d+:in `call}
- end
+ # assert application trace refers to line that calls method_that_raises is first
+ assert_select '#Application-Trace' do
+ assert_select 'pre code a:first', %r{test/dispatch/debug_exceptions_test\.rb:\d+:in `call}
+ end
- # assert framework trace that that threw the error is first
- assert_select '#Framework-Trace' do
- assert_select 'pre code a:first', /method_that_raises/
+ # assert framework trace that that threw the error is first
+ assert_select '#Framework-Trace' do
+ assert_select 'pre code a:first', /method_that_raises/
+ end
end
end
end
diff --git a/actionpack/test/dispatch/live_response_test.rb b/actionpack/test/dispatch/live_response_test.rb
index 5cfa5f7b3b..1c128365c7 100644
--- a/actionpack/test/dispatch/live_response_test.rb
+++ b/actionpack/test/dispatch/live_response_test.rb
@@ -65,7 +65,7 @@ module ActionController
latch = Concurrent::CountDownLatch.new
t = Thread.new {
- @response.stream.each do |chunk|
+ @response.stream.each do
latch.count_down
end
}
diff --git a/actionpack/test/dispatch/routing/inspector_test.rb b/actionpack/test/dispatch/routing/inspector_test.rb
index 4047214843..24bd4b04ec 100644
--- a/actionpack/test/dispatch/routing/inspector_test.rb
+++ b/actionpack/test/dispatch/routing/inspector_test.rb
@@ -12,12 +12,6 @@ module ActionDispatch
class RoutesInspectorTest < ActiveSupport::TestCase
def setup
@set = ActionDispatch::Routing::RouteSet.new
- app = ActiveSupport::OrderedOptions.new
- app.config = ActiveSupport::OrderedOptions.new
- app.config.assets = ActiveSupport::OrderedOptions.new
- app.config.assets.prefix = '/sprockets'
- Rails.stubs(:application).returns(app)
- Rails.stubs(:env).returns("development")
end
def draw(options = {}, &block)
@@ -316,9 +310,6 @@ module ActionDispatch
def test_inspect_routes_shows_resources_route_when_assets_disabled
@set = ActionDispatch::Routing::RouteSet.new
- app = ActiveSupport::OrderedOptions.new
-
- Rails.stubs(:application).returns(app)
output = draw do
get '/cart', to: 'cart#show'
diff --git a/actionview/lib/action_view/layouts.rb b/actionview/lib/action_view/layouts.rb
index 9d636c8c9e..cabba967c9 100644
--- a/actionview/lib/action_view/layouts.rb
+++ b/actionview/lib/action_view/layouts.rb
@@ -277,7 +277,7 @@ module ActionView
remove_possible_method(:_layout)
prefixes = _implied_layout_name =~ /\blayouts/ ? [] : ["layouts"]
- default_behavior = "lookup_context.find_all('#{_implied_layout_name}', #{prefixes.inspect}).first || super"
+ default_behavior = "lookup_context.find_all('#{_implied_layout_name}', #{prefixes.inspect}, false, [], { formats: formats }).first || super"
name_clause = if name
default_behavior
else
@@ -316,7 +316,7 @@ module ActionView
end
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
- def _layout
+ def _layout(formats)
if _conditional_layout?
#{layout_definition}
else
@@ -372,7 +372,7 @@ module ActionView
end
# This will be overwritten by _write_layout_method
- def _layout; end
+ def _layout(*); end
# Determine the layout for a given name, taking into account the name type.
#
@@ -382,8 +382,8 @@ module ActionView
case name
when String then _normalize_layout(name)
when Proc then name
- when true then Proc.new { _default_layout(true) }
- when :default then Proc.new { _default_layout(false) }
+ when true then Proc.new { |formats| _default_layout(formats, true) }
+ when :default then Proc.new { |formats| _default_layout(formats, false) }
when false, nil then nil
else
raise ArgumentError,
@@ -399,14 +399,15 @@ module ActionView
# Optionally raises an exception if the layout could not be found.
#
# ==== Parameters
+ # * <tt>formats</tt> - The formats accepted to this layout
# * <tt>require_layout</tt> - If set to true and layout is not found,
# an ArgumentError exception is raised (defaults to false)
#
# ==== Returns
# * <tt>template</tt> - The template object for the default layout (or nil)
- def _default_layout(require_layout = false)
+ def _default_layout(formats, require_layout = false)
begin
- value = _layout if action_has_layout?
+ value = _layout(formats) if action_has_layout?
rescue NameError => e
raise e, "Could not render layout: #{e.message}"
end
diff --git a/actionview/lib/action_view/lookup_context.rb b/actionview/lib/action_view/lookup_context.rb
index f4a10aa393..fba9a44cb1 100644
--- a/actionview/lib/action_view/lookup_context.rb
+++ b/actionview/lib/action_view/lookup_context.rb
@@ -229,21 +229,5 @@ module ActionView
super(default_locale)
end
-
- # Uses the first format in the formats array for layout lookup.
- def with_layout_format
- if formats.size == 1
- yield
- else
- old_formats = formats
- _set_detail(:formats, formats[0,1])
-
- begin
- yield
- ensure
- _set_detail(:formats, old_formats)
- end
- end
- end
end
end
diff --git a/actionview/lib/action_view/renderer/streaming_template_renderer.rb b/actionview/lib/action_view/renderer/streaming_template_renderer.rb
index 3ab2cd36fc..f38e2764d0 100644
--- a/actionview/lib/action_view/renderer/streaming_template_renderer.rb
+++ b/actionview/lib/action_view/renderer/streaming_template_renderer.rb
@@ -47,7 +47,7 @@ module ActionView
return [super] unless layout_name && template.supports_streaming?
locals ||= {}
- layout = layout_name && find_layout(layout_name, locals.keys)
+ layout = layout_name && find_layout(layout_name, locals.keys, [formats.first])
Body.new do |buffer|
delayed_render(buffer, template, layout, @view, locals)
diff --git a/actionview/lib/action_view/renderer/template_renderer.rb b/actionview/lib/action_view/renderer/template_renderer.rb
index dbb4855e39..75217e1630 100644
--- a/actionview/lib/action_view/renderer/template_renderer.rb
+++ b/actionview/lib/action_view/renderer/template_renderer.rb
@@ -57,7 +57,7 @@ module ActionView
end
def render_with_layout(path, locals) #:nodoc:
- layout = path && find_layout(path, locals.keys)
+ layout = path && find_layout(path, locals.keys, [formats.first])
content = yield(layout)
if layout
@@ -72,27 +72,28 @@ module ActionView
# This is the method which actually finds the layout using details in the lookup
# context object. If no layout is found, it checks if at least a layout with
# the given name exists across all details before raising the error.
- def find_layout(layout, keys)
- with_layout_format { resolve_layout(layout, keys) }
+ def find_layout(layout, keys, formats)
+ resolve_layout(layout, keys, formats)
end
- def resolve_layout(layout, keys)
+ def resolve_layout(layout, keys, formats)
+ details = @details.dup
+ details[:formats] = formats
+
case layout
when String
begin
if layout =~ /^\//
- with_fallbacks { find_template(layout, nil, false, keys, @details) }
+ with_fallbacks { find_template(layout, nil, false, keys, details) }
else
- find_template(layout, nil, false, keys, @details)
+ find_template(layout, nil, false, keys, details)
end
rescue ActionView::MissingTemplate
all_details = @details.merge(:formats => @lookup_context.default_formats)
raise unless template_exists?(layout, nil, false, keys, all_details)
end
when Proc
- resolve_layout(layout.call, keys)
- when FalseClass
- nil
+ resolve_layout(layout.call(formats), keys, formats)
else
layout
end
diff --git a/activejob/CHANGELOG.md b/activejob/CHANGELOG.md
index 637096e935..965b556fab 100644
--- a/activejob/CHANGELOG.md
+++ b/activejob/CHANGELOG.md
@@ -1,3 +1,8 @@
+* Implement a simple `AsyncJob` processor and associated `AsyncAdapter` that
+ queue jobs to a `concurrent-ruby` thread pool.
+
+ *Jerry D'Antonio*
+
* Implement `provider_job_id` for `queue_classic` adapter. This requires the
latest, currently unreleased, version of queue_classic.
diff --git a/activejob/Rakefile b/activejob/Rakefile
index 8c86df3c91..d9648a7f16 100644
--- a/activejob/Rakefile
+++ b/activejob/Rakefile
@@ -1,6 +1,6 @@
require 'rake/testtask'
-ACTIVEJOB_ADAPTERS = %w(inline delayed_job qu que queue_classic resque sidekiq sneakers sucker_punch backburner test)
+ACTIVEJOB_ADAPTERS = %w(async inline delayed_job qu que queue_classic resque sidekiq sneakers sucker_punch backburner test)
ACTIVEJOB_ADAPTERS -= %w(queue_classic) if defined?(JRUBY_VERSION)
task default: :test
diff --git a/activejob/lib/active_job.rb b/activejob/lib/active_job.rb
index 3d4f63b261..eb8091a805 100644
--- a/activejob/lib/active_job.rb
+++ b/activejob/lib/active_job.rb
@@ -32,6 +32,7 @@ module ActiveJob
autoload :Base
autoload :QueueAdapters
autoload :ConfiguredJob
+ autoload :AsyncJob
autoload :TestCase
autoload :TestHelper
end
diff --git a/activejob/lib/active_job/async_job.rb b/activejob/lib/active_job/async_job.rb
new file mode 100644
index 0000000000..7fcffc4c24
--- /dev/null
+++ b/activejob/lib/active_job/async_job.rb
@@ -0,0 +1,75 @@
+require 'concurrent'
+require 'thread_safe'
+
+module ActiveJob
+ # == Active Job Async Job
+ #
+ # When enqueueing jobs with Async Job each job will be executed asynchronously
+ # on a +concurrent-ruby+ thread pool. All job data is retained in memory.
+ # Because job data is not saved to a persistent datastore there is no
+ # additional infrastructure needed and jobs process quickly. The lack of
+ # persistence, however, means that all unprocessed jobs will be lost on
+ # application restart. Therefore in-memory queue adapters are unsuitable for
+ # most production environments but are excellent for development and testing.
+ #
+ # Read more about Concurrent Ruby {here}[https://github.com/ruby-concurrency/concurrent-ruby].
+ #
+ # To use Async Job set the queue_adapter config to +:async+.
+ #
+ # Rails.application.config.active_job.queue_adapter = :async
+ #
+ # Async Job supports job queues specified with +queue_as+. Queues are created
+ # automatically as needed and each has its own thread pool.
+ class AsyncJob
+
+ DEFAULT_EXECUTOR_OPTIONS = {
+ min_threads: [2, Concurrent.processor_count].max,
+ max_threads: Concurrent.processor_count * 10,
+ auto_terminate: true,
+ idletime: 60, # 1 minute
+ max_queue: 0, # unlimited
+ fallback_policy: :caller_runs # shouldn't matter -- 0 max queue
+ }.freeze
+
+ QUEUES = ThreadSafe::Cache.new do |hash, queue_name| #:nodoc:
+ hash.compute_if_absent(queue_name) { ActiveJob::AsyncJob.create_thread_pool }
+ end
+
+ class << self
+ # Forces jobs to process immediately when testing the Active Job gem.
+ # This should only be called from within unit tests.
+ def perform_immediately! #:nodoc:
+ @perform_immediately = true
+ end
+
+ # Allows jobs to run asynchronously when testing the Active Job gem.
+ # This should only be called from within unit tests.
+ def perform_asynchronously! #:nodoc:
+ @perform_immediately = false
+ end
+
+ def create_thread_pool #:nodoc:
+ if @perform_immediately
+ Concurrent::ImmediateExecutor.new
+ else
+ Concurrent::ThreadPoolExecutor.new(DEFAULT_EXECUTOR_OPTIONS)
+ end
+ end
+
+ def enqueue(job_data, queue: 'default') #:nodoc:
+ QUEUES[queue].post(job_data) { |job| ActiveJob::Base.execute(job) }
+ end
+
+ def enqueue_at(job_data, timestamp, queue: 'default') #:nodoc:
+ delay = timestamp - Time.current.to_f
+ if delay > 0
+ Concurrent::ScheduledTask.execute(delay, args: [job_data], executor: QUEUES[queue]) do |job|
+ ActiveJob::Base.execute(job)
+ end
+ else
+ enqueue(job_data, queue: queue)
+ end
+ end
+ end
+ end
+end
diff --git a/activejob/lib/active_job/queue_adapters.rb b/activejob/lib/active_job/queue_adapters.rb
index e8ceabaeba..aeb1fe1e73 100644
--- a/activejob/lib/active_job/queue_adapters.rb
+++ b/activejob/lib/active_job/queue_adapters.rb
@@ -12,6 +12,8 @@ module ActiveJob
# * {Sidekiq}[http://sidekiq.org]
# * {Sneakers}[https://github.com/jondot/sneakers]
# * {Sucker Punch}[https://github.com/brandonhilkert/sucker_punch]
+ # * {Active Job Async Job}[http://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/AsyncAdapter.html]
+ # * {Active Job Inline}[http://api.rubyonrails.org/classes/ActiveJob/QueueAdapters/InlineAdapter.html]
#
# === Backends Features
#
@@ -26,6 +28,7 @@ module ActiveJob
# | Sidekiq | Yes | Yes | Yes | Queue | No | Job |
# | Sneakers | Yes | Yes | No | Queue | Queue | No |
# | Sucker Punch | Yes | Yes | No | No | No | No |
+ # | Active Job Async | Yes | Yes | Yes | No | No | No |
# | Active Job Inline | No | Yes | N/A | N/A | N/A | N/A |
#
# ==== Async
@@ -96,9 +99,15 @@ module ActiveJob
#
# N/A: The adapter does not run in a separate process, and therefore doesn't
# support retries.
+ #
+ # === Async and Inline Queue Adapters
+ #
+ # Active Job has two built-in queue adapters intended for development and
+ # testing: +:async+ and +:inline+.
module QueueAdapters
extend ActiveSupport::Autoload
+ autoload :AsyncAdapter
autoload :InlineAdapter
autoload :BackburnerAdapter
autoload :DelayedJobAdapter
diff --git a/activejob/lib/active_job/queue_adapters/async_adapter.rb b/activejob/lib/active_job/queue_adapters/async_adapter.rb
new file mode 100644
index 0000000000..3fc27f56e7
--- /dev/null
+++ b/activejob/lib/active_job/queue_adapters/async_adapter.rb
@@ -0,0 +1,23 @@
+require 'active_job/async_job'
+
+module ActiveJob
+ module QueueAdapters
+ # == Active Job Async adapter
+ #
+ # When enqueueing jobs with the Async adapter the job will be executed
+ # asynchronously using {AsyncJob}[http://api.rubyonrails.org/classes/ActiveJob/AsyncJob.html].
+ #
+ # To use +AsyncJob+ set the queue_adapter config to +:async+.
+ #
+ # Rails.application.config.active_job.queue_adapter = :async
+ class AsyncAdapter
+ def enqueue(job) #:nodoc:
+ ActiveJob::AsyncJob.enqueue(job.serialize, queue: job.queue_name)
+ end
+
+ def enqueue_at(job, timestamp) #:nodoc:
+ ActiveJob::AsyncJob.enqueue_at(job.serialize, timestamp, queue: job.queue_name)
+ end
+ end
+ end
+end
diff --git a/activejob/test/adapters/async.rb b/activejob/test/adapters/async.rb
new file mode 100644
index 0000000000..df58027599
--- /dev/null
+++ b/activejob/test/adapters/async.rb
@@ -0,0 +1,5 @@
+require 'concurrent'
+require 'active_job/async_job'
+
+ActiveJob::Base.queue_adapter = :async
+ActiveJob::AsyncJob.perform_immediately!
diff --git a/activejob/test/cases/async_job_test.rb b/activejob/test/cases/async_job_test.rb
new file mode 100644
index 0000000000..2642cfc608
--- /dev/null
+++ b/activejob/test/cases/async_job_test.rb
@@ -0,0 +1,42 @@
+require 'helper'
+require 'jobs/hello_job'
+require 'jobs/queue_as_job'
+
+class AsyncJobTest < ActiveSupport::TestCase
+ def using_async_adapter?
+ ActiveJob::Base.queue_adapter.is_a? ActiveJob::QueueAdapters::AsyncAdapter
+ end
+
+ setup do
+ ActiveJob::AsyncJob.perform_asynchronously!
+ end
+
+ teardown do
+ ActiveJob::AsyncJob::QUEUES.clear
+ ActiveJob::AsyncJob.perform_immediately!
+ end
+
+ test "#create_thread_pool returns a thread_pool" do
+ thread_pool = ActiveJob::AsyncJob.create_thread_pool
+ assert thread_pool.is_a? Concurrent::ExecutorService
+ assert_not thread_pool.is_a? Concurrent::ImmediateExecutor
+ end
+
+ test "#create_thread_pool returns an ImmediateExecutor after #perform_immediately! is called" do
+ ActiveJob::AsyncJob.perform_immediately!
+ thread_pool = ActiveJob::AsyncJob.create_thread_pool
+ assert thread_pool.is_a? Concurrent::ImmediateExecutor
+ end
+
+ test "enqueuing without specifying a queue uses the default queue" do
+ skip unless using_async_adapter?
+ HelloJob.perform_later
+ assert ActiveJob::AsyncJob::QUEUES.key? 'default'
+ end
+
+ test "enqueuing to a queue that does not exist creates the queue" do
+ skip unless using_async_adapter?
+ QueueAsJob.perform_later
+ assert ActiveJob::AsyncJob::QUEUES.key? QueueAsJob::MY_QUEUE.to_s
+ end
+end
diff --git a/activejob/test/integration/queuing_test.rb b/activejob/test/integration/queuing_test.rb
index ca8047ef0b..125ba54302 100644
--- a/activejob/test/integration/queuing_test.rb
+++ b/activejob/test/integration/queuing_test.rb
@@ -11,7 +11,7 @@ class QueuingTest < ActiveSupport::TestCase
end
test 'should not run jobs queued on a non-listening queue' do
- skip if adapter_is?(:inline, :sucker_punch, :que)
+ skip if adapter_is?(:inline, :async, :sucker_punch, :que)
old_queue = TestJob.queue_name
begin
diff --git a/activejob/test/jobs/queue_as_job.rb b/activejob/test/jobs/queue_as_job.rb
new file mode 100644
index 0000000000..897aef52e5
--- /dev/null
+++ b/activejob/test/jobs/queue_as_job.rb
@@ -0,0 +1,10 @@
+require_relative '../support/job_buffer'
+
+class QueueAsJob < ActiveJob::Base
+ MY_QUEUE = :low_priority
+ queue_as MY_QUEUE
+
+ def perform(greeter = "David")
+ JobBuffer.add("#{greeter} says hello")
+ end
+end
diff --git a/activejob/test/support/integration/adapters/async.rb b/activejob/test/support/integration/adapters/async.rb
new file mode 100644
index 0000000000..42beb12b1f
--- /dev/null
+++ b/activejob/test/support/integration/adapters/async.rb
@@ -0,0 +1,9 @@
+module AsyncJobsManager
+ def setup
+ ActiveJob::Base.queue_adapter = :async
+ end
+
+ def clear_jobs
+ ActiveJob::AsyncJob::QUEUES.clear
+ end
+end
diff --git a/activemodel/lib/active_model/serialization.rb b/activemodel/lib/active_model/serialization.rb
index 58d68d9620..44bc9efa47 100644
--- a/activemodel/lib/active_model/serialization.rb
+++ b/activemodel/lib/active_model/serialization.rb
@@ -31,12 +31,10 @@ module ActiveModel
# of the attributes hash's keys. In order to override this behavior, take a look
# at the private method +read_attribute_for_serialization+.
#
- # Most of the time though, either the JSON or XML serializations are needed.
- # Both of these modules automatically include the
- # <tt>ActiveModel::Serialization</tt> module, so there is no need to
- # explicitly include it.
+ # JSON Serialization module is automatically include the <tt>ActiveModel::Serialization</tt>
+ # module, so there is no need to explicitly include it.
#
- # A minimal implementation including XML and JSON would be:
+ # A minimal implementation including JSON would be:
#
# class Person
# include ActiveModel::Serializers::JSON
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index a830b0e0e4..19ef37e228 100644
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -619,10 +619,10 @@ module ActiveRecord
# @tag = @post.tags.build name: "ruby"
# @tag.save
#
- # The last line ought to save the through record (a <tt>Taggable</tt>). This will only work if the
+ # The last line ought to save the through record (a <tt>Tagging</tt>). This will only work if the
# <tt>:inverse_of</tt> is set:
#
- # class Taggable < ActiveRecord::Base
+ # class Tagging < ActiveRecord::Base
# belongs_to :post
# belongs_to :tag, inverse_of: :taggings
# end
@@ -643,7 +643,7 @@ module ActiveRecord
# You can turn off the automatic detection of inverse associations by setting
# the <tt>:inverse_of</tt> option to <tt>false</tt> like so:
#
- # class Taggable < ActiveRecord::Base
+ # class Tagging < ActiveRecord::Base
# belongs_to :tag, inverse_of: false
# end
#
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 55a7e053bc..4b66d8cd36 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -1,5 +1,4 @@
require 'yaml'
-require 'set'
require 'active_support/benchmarkable'
require 'active_support/dependencies'
require 'active_support/descendants_tracker'
diff --git a/activerecord/lib/active_record/enum.rb b/activerecord/lib/active_record/enum.rb
index 91a13cb0cd..4902fcb1a2 100644
--- a/activerecord/lib/active_record/enum.rb
+++ b/activerecord/lib/active_record/enum.rb
@@ -18,10 +18,9 @@ module ActiveRecord
# conversation.archived? # => true
# conversation.status # => "archived"
#
- # # conversation.update! status: 1
+ # # conversation.status = 1
# conversation.status = "archived"
#
- # # conversation.update! status: nil
# conversation.status = nil
# conversation.status.nil? # => true
# conversation.status # => nil
diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb
index 04c6124eef..923dc1799a 100644
--- a/activerecord/lib/active_record/migration.rb
+++ b/activerecord/lib/active_record/migration.rb
@@ -459,7 +459,7 @@ module ActiveRecord
# Or equivalently, if +TenderloveMigration+ is defined as in the
# documentation for Migration:
#
- # require_relative '2012121212_tenderlove_migration'
+ # require_relative '20121212123456_tenderlove_migration'
#
# class FixupTLMigration < ActiveRecord::Migration
# def change
diff --git a/activerecord/lib/active_record/migration/command_recorder.rb b/activerecord/lib/active_record/migration/command_recorder.rb
index dcc2362397..b52e89d792 100644
--- a/activerecord/lib/active_record/migration/command_recorder.rb
+++ b/activerecord/lib/active_record/migration/command_recorder.rb
@@ -14,6 +14,13 @@ module ActiveRecord
# * rename_index
# * rename_table
class CommandRecorder
+ ReversibleAndIrreversibleMethods = [:create_table, :create_join_table, :rename_table, :add_column, :remove_column,
+ :rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps,
+ :change_column_default, :add_reference, :remove_reference, :transaction,
+ :drop_join_table, :drop_table, :execute_block, :enable_extension,
+ :change_column, :execute, :remove_columns, :change_column_null,
+ :add_foreign_key, :remove_foreign_key
+ ]
include JoinTable
attr_accessor :commands, :delegate, :reverting
@@ -70,14 +77,7 @@ module ActiveRecord
super || delegate.respond_to?(*args)
end
- [:create_table, :create_join_table, :rename_table, :add_column, :remove_column,
- :rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps,
- :add_reference, :remove_reference, :transaction,
- :drop_join_table, :drop_table, :execute_block, :enable_extension,
- :change_column, :execute, :remove_columns, :change_column_null,
- :add_foreign_key, :remove_foreign_key
- # irreversible methods need to be here too
- ].each do |method|
+ ReversibleAndIrreversibleMethods.each do |method|
class_eval <<-EOV, __FILE__, __LINE__ + 1
def #{method}(*args, &block) # def create_table(*args, &block)
record(:"#{method}", args, &block) # record(:create_table, args, &block)
diff --git a/activerecord/test/cases/invertible_migration_test.rb b/activerecord/test/cases/invertible_migration_test.rb
index 99230aa3d5..3bc4fa379f 100644
--- a/activerecord/test/cases/invertible_migration_test.rb
+++ b/activerecord/test/cases/invertible_migration_test.rb
@@ -1,5 +1,8 @@
require "cases/helper"
+class Horse < ActiveRecord::Base
+end
+
module ActiveRecord
class InvertibleMigrationTest < ActiveRecord::TestCase
class SilentMigration < ActiveRecord::Migration
@@ -76,6 +79,20 @@ module ActiveRecord
end
end
+ class ChangeColumnDefault1 < SilentMigration
+ def change
+ create_table("horses") do |t|
+ t.column :name, :string, default: "Sekitoba"
+ end
+ end
+ end
+
+ class ChangeColumnDefault2 < SilentMigration
+ def change
+ change_column_default :horses, :name, from: "Sekitoba", to: "Diomed"
+ end
+ end
+
class LegacyMigration < ActiveRecord::Migration
def self.up
create_table("horses") do |t|
@@ -223,6 +240,22 @@ module ActiveRecord
assert !revert.connection.table_exists?("horses")
end
+ def test_migrate_revert_change_column_default
+ index_definition = ["horses", [:name, :color]]
+ migration1 = ChangeColumnDefault1.new
+ migration1.migrate(:up)
+ assert_equal "Sekitoba", Horse.new.name
+
+ migration2 = ChangeColumnDefault2.new
+ migration2.migrate(:up)
+ Horse.reset_column_information
+ assert_equal "Diomed", Horse.new.name
+
+ migration2.migrate(:down)
+ Horse.reset_column_information
+ assert_equal "Sekitoba", Horse.new.name
+ end
+
def test_revert_order
block = Proc.new{|t| t.string :name }
recorder = ActiveRecord::Migration::CommandRecorder.new(ActiveRecord::Base.connection)
diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb
index 11e42f28dc..128a242495 100644
--- a/activerecord/test/cases/migration_test.rb
+++ b/activerecord/test/cases/migration_test.rb
@@ -115,7 +115,7 @@ class MigrationTest < ActiveRecord::TestCase
end
def test_migration_version
- ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/version_check", 20131219224947)
+ assert_nothing_raised { ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/version_check", 20131219224947) }
end
def test_create_table_with_force_true_does_not_drop_nonexisting_table
diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb
index 42e7507631..cdf63957f4 100644
--- a/activerecord/test/cases/persistence_test.rb
+++ b/activerecord/test/cases/persistence_test.rb
@@ -17,6 +17,7 @@ require 'models/minivan'
require 'models/owner'
require 'models/person'
require 'models/pet'
+require 'models/ship'
require 'models/toy'
require 'rexml/document'
diff --git a/activerecord/test/cases/readonly_test.rb b/activerecord/test/cases/readonly_test.rb
index 1c919f0b57..5f6eb41240 100644
--- a/activerecord/test/cases/readonly_test.rb
+++ b/activerecord/test/cases/readonly_test.rb
@@ -7,6 +7,7 @@ require 'models/computer'
require 'models/project'
require 'models/reader'
require 'models/person'
+require 'models/ship'
class ReadOnlyTest < ActiveRecord::TestCase
fixtures :authors, :posts, :comments, :developers, :projects, :developers_projects, :people, :readers
diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec
index 6d2ae9be76..67b6663915 100644
--- a/activesupport/activesupport.gemspec
+++ b/activesupport/activesupport.gemspec
@@ -25,6 +25,6 @@ Gem::Specification.new do |s|
s.add_dependency 'tzinfo', '~> 1.1'
s.add_dependency 'minitest', '~> 5.1'
s.add_dependency 'thread_safe','~> 0.3', '>= 0.3.4'
- s.add_dependency 'concurrent-ruby', '~> 0.9.0'
+ s.add_dependency 'concurrent-ruby', '~> 0.9.1'
s.add_dependency 'method_source'
end
diff --git a/activesupport/lib/active_support/core_ext/kernel/reporting.rb b/activesupport/lib/active_support/core_ext/kernel/reporting.rb
index 9189e6d977..8afc258df8 100644
--- a/activesupport/lib/active_support/core_ext/kernel/reporting.rb
+++ b/activesupport/lib/active_support/core_ext/kernel/reporting.rb
@@ -1,5 +1,3 @@
-require 'tempfile'
-
module Kernel
# Sets $VERBOSE to nil for the duration of the block and back to its original
# value afterwards.
diff --git a/activesupport/lib/active_support/core_ext/string/strip.rb b/activesupport/lib/active_support/core_ext/string/strip.rb
index 086c610976..9fdd9d8d2e 100644
--- a/activesupport/lib/active_support/core_ext/string/strip.rb
+++ b/activesupport/lib/active_support/core_ext/string/strip.rb
@@ -17,8 +17,8 @@ class String
#
# the user would see the usage message aligned against the left margin.
#
- # Technically, it looks for the least indented line in the whole string, and removes
- # that amount of leading whitespace.
+ # Technically, it looks for the least indented non-empty line
+ # in the whole string, and removes that amount of leading whitespace.
def strip_heredoc
indent = scan(/^[ \t]*(?=\S)/).min.try(:size) || 0
gsub(/^[ \t]{#{indent}}/, '')
diff --git a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
index 9b264cbb79..6572ff78a6 100644
--- a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
+++ b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb
@@ -20,7 +20,7 @@ module ActiveSupport
private
def method_missing(called, *args, &block)
- warn caller, called, args
+ warn caller_locations, called, args
target.__send__(called, *args, &block)
end
end
diff --git a/activesupport/lib/active_support/deprecation/reporting.rb b/activesupport/lib/active_support/deprecation/reporting.rb
index a7d265d732..bbe25c9260 100644
--- a/activesupport/lib/active_support/deprecation/reporting.rb
+++ b/activesupport/lib/active_support/deprecation/reporting.rb
@@ -14,7 +14,7 @@ module ActiveSupport
def warn(message = nil, callstack = nil)
return if silenced
- callstack ||= caller(2)
+ callstack ||= caller_locations(2)
deprecation_message(callstack, message).tap do |m|
behavior.each { |b| b.call(m, callstack) }
end
@@ -37,7 +37,7 @@ module ActiveSupport
end
def deprecation_warning(deprecated_method_name, message = nil, caller_backtrace = nil)
- caller_backtrace ||= caller(2)
+ caller_backtrace ||= caller_locations(2)
deprecated_method_warning(deprecated_method_name, message).tap do |msg|
warn(msg, caller_backtrace)
end
@@ -79,6 +79,17 @@ module ActiveSupport
end
def extract_callstack(callstack)
+ return _extract_callstack(callstack) if callstack.first.is_a? String
+
+ rails_gem_root = File.expand_path("../../../../..", __FILE__) + "/"
+ offending_line = callstack.find { |frame|
+ !frame.absolute_path.start_with?(rails_gem_root)
+ } || callstack.first
+ [offending_line.path, offending_line.lineno, offending_line.label]
+ end
+
+ def _extract_callstack(callstack)
+ warn "Please pass `caller_locations` to the deprecation API" if $VERBOSE
rails_gem_root = File.expand_path("../../../../..", __FILE__) + "/"
offending_line = callstack.find { |line| !line.start_with?(rails_gem_root) } || callstack.first
if offending_line
diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb
index f8f1b9ac2c..5dd9c423e3 100644
--- a/activesupport/lib/active_support/time_with_zone.rb
+++ b/activesupport/lib/active_support/time_with_zone.rb
@@ -246,6 +246,7 @@ module ActiveSupport
utc.future?
end
+ # Returns +true+ if +other+ is equal to current object.
def eql?(other)
other.eql?(utc)
end
@@ -329,6 +330,11 @@ module ActiveSupport
EOV
end
+ # Returns Array of parts of Time in sequence of
+ # [seconds, minutes, hours, day, month, year, weekday, yearday, dst?, zone].
+ #
+ # now = Time.zone.now # => Tue, 18 Aug 2015 02:29:27 UTC +00:00
+ # now.to_a # => [27, 29, 2, 18, 8, 2015, 2, 230, false, "UTC"]
def to_a
[time.sec, time.min, time.hour, time.day, time.mon, time.year, time.wday, time.yday, dst?, zone]
end
@@ -358,11 +364,14 @@ module ActiveSupport
utc.to_r
end
- # Return an instance of Time in the system timezone.
+ # Returns an instance of Time in the system timezone.
def to_time
utc.to_time
end
+ # Returns an instance of DateTime in the UTC timezone.
+ #
+ # Time.zone.now.to_datetime # => Tue, 18 Aug 2015 02:32:20 +0000
def to_datetime
utc.to_datetime.new_offset(Rational(utc_offset, 86_400))
end
diff --git a/guides/source/active_record_migrations.md b/guides/source/active_record_migrations.md
index 4e5902fb3d..67cd86c19b 100644
--- a/guides/source/active_record_migrations.md
+++ b/guides/source/active_record_migrations.md
@@ -652,7 +652,7 @@ can't be done.
You can use Active Record's ability to rollback migrations using the `revert` method:
```ruby
-require_relative '2012121212_example_migration'
+require_relative '20121212123456_example_migration'
class FixupExampleMigration < ActiveRecord::Migration
def change
diff --git a/guides/source/debugging_rails_applications.md b/guides/source/debugging_rails_applications.md
index fe8757fbd5..a05abb61d6 100644
--- a/guides/source/debugging_rails_applications.md
+++ b/guides/source/debugging_rails_applications.md
@@ -623,7 +623,8 @@ Processing by ArticlesController#index as HTML
If we use `next`, we won't go deep inside method calls. Instead, `byebug` will
go to the next line within the same context. In this case, it is the last line
of the current method, so `byebug` will return to the next line of the caller
-+method.
+method.
+
```
(byebug) next
diff --git a/guides/source/testing.md b/guides/source/testing.md
index 3a691220cf..1cc49a36d2 100644
--- a/guides/source/testing.md
+++ b/guides/source/testing.md
@@ -50,7 +50,7 @@ By default, every Rails application has three environments: development, test, a
Each environment's configuration can be modified similarly. In this case, we can modify our test environment by changing the options found in `config/environments/test.rb`.
-NOTE: Your test are run under RAILS_ENV=test.
+NOTE: Your tests are run under `RAILS_ENV=test`.
### Rails meets Minitest
@@ -336,7 +336,8 @@ All the basic assertions such as `assert_equal` defined in `Minitest::Assertions
Each of these classes include `Minitest::Assertions`, allowing us to use all of the basic assertions in our tests.
-NOTE: For more information on `Minitest`, refer to [Minitest](http://docs.seattlerb.org/minitest)
+NOTE: For more information on `Minitest`, refer to [its
+documentation](http://docs.seattlerb.org/minitest).
### The Rails Test Runner
@@ -355,7 +356,8 @@ Finished tests in 0.009262s, 107.9680 tests/s, 107.9680 assertions/s.
This will run all test methods from the test case.
-You can also run a particular test method from the test case by providing the `-n` or `--name` flag and the `test method name`.
+You can also run a particular test method from the test case by providing the
+`-n` or `--name` flag and the test's method name.
```bash
$ bin/rails test test/models/article_test.rb -n test_the_truth
@@ -469,7 +471,8 @@ user_<%= n %>:
#### Fixtures in Action
-Rails by default automatically loads all fixtures from the `test/fixtures` directory for your models and controllers test. Loading involves three steps:
+Rails automatically loads all fixtures from the `test/fixtures` directory by
+default. Loading involves three steps:
1. Remove any existing data from the table corresponding to the fixture
2. Load the fixture data into the table
@@ -505,7 +508,8 @@ Model Testing
Model tests are used to test the various models of your application.
-For creating Rails model tests, we use the 'test/model' directory for your application. Rails provides a generator to create an model test skeleton for you.
+Rails model tests are stored under the `test/models` directory. Rails provides
+a generator to create a model test skeleton for you.
```bash
$ bin/rails generate test_unit:model article title:string body:text
@@ -563,7 +567,8 @@ We'll start by generating our integration test skeleton:
$ bin/rails generate integration_test blog_flow
```
-It should have created a test file placeholder for us, with the output of the previous command you should see:
+It should have created a test file placeholder for us. With the output of the
+previous command you should see:
```bash
invoke test_unit
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index 21adac272d..faf6846e4b 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,3 +1,7 @@
+* `rails server` will now honour the `PORT` environment variable
+
+ *David Cornu*
+
* Plugins generated using `rails plugin new` are now generated with the
version number set to 0.1.0.
diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb
index c8fb58ab05..d3ea441f8e 100644
--- a/railties/lib/rails/commands/server.rb
+++ b/railties/lib/rails/commands/server.rb
@@ -86,7 +86,7 @@ module Rails
def default_options
super.merge({
- Port: 3000,
+ Port: ENV.fetch('PORT', 3000).to_i,
DoNotReverseLookup: true,
environment: (ENV['RAILS_ENV'] || ENV['RACK_ENV'] || "development").dup,
daemonize: false,
diff --git a/railties/test/application/initializers/frameworks_test.rb b/railties/test/application/initializers/frameworks_test.rb
index 7bba910b9e..6e3707cc27 100644
--- a/railties/test/application/initializers/frameworks_test.rb
+++ b/railties/test/application/initializers/frameworks_test.rb
@@ -1,5 +1,4 @@
require "isolation/abstract_unit"
-require 'set'
module ApplicationTests
class FrameworksTest < ActiveSupport::TestCase
diff --git a/railties/test/commands/server_test.rb b/railties/test/commands/server_test.rb
index 7a063aeddf..3be4a74f74 100644
--- a/railties/test/commands/server_test.rb
+++ b/railties/test/commands/server_test.rb
@@ -44,6 +44,13 @@ class Rails::ServerTest < ActiveSupport::TestCase
end
end
+ def test_environment_with_port
+ switch_env "PORT", "1234" do
+ server = Rails::Server.new
+ assert_equal 1234, server.options[:Port]
+ end
+ end
+
def test_caching_without_option
args = []
options = Rails::Server::Options.new.parse!(args)
diff --git a/railties/test/path_generation_test.rb b/railties/test/path_generation_test.rb
index 27e64b97b7..a16adc72a6 100644
--- a/railties/test/path_generation_test.rb
+++ b/railties/test/path_generation_test.rb
@@ -11,26 +11,26 @@ class PathGenerationTest < ActiveSupport::TestCase
super()
end
- class Dispatcher < ActionDispatch::Routing::RouteSet::Dispatcher
- def initialize(defaults, set, block)
- super(defaults)
+ class Request < DelegateClass(ActionDispatch::Request)
+ def initialize(target, url_helpers, block)
+ super(target)
+ @url_helpers = url_helpers
@block = block
- @set = set
end
- def controller_reference(controller_param)
+ def controller_class
+ url_helpers = @url_helpers
block = @block
- set = @set
Class.new(ActionController::Base) {
- include set.url_helpers
+ include url_helpers
define_method(:process) { |name| block.call(self) }
def to_a; [200, {}, []]; end
}
end
end
- def dispatcher defaults
- TestSet::Dispatcher.new defaults, self, @block
+ def make_request(env)
+ Request.new super, self.url_helpers, @block
end
end
diff --git a/tasks/release.rb b/tasks/release.rb
index d8c1390eef..2c7e927679 100644
--- a/tasks/release.rb
+++ b/tasks/release.rb
@@ -98,7 +98,7 @@ namespace :all do
task :push => FRAMEWORKS.map { |f| "#{f}:push" } + ['rails:push']
task :ensure_clean_state do
- unless `git status -s | grep -v RAILS_VERSION`.strip.empty?
+ unless `git status -s | grep -v 'RAILS_VERSION\\|CHANGELOG'`.strip.empty?
abort "[ABORTING] `git status` reports a dirty tree. Make sure all changes are committed"
end