aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile1
-rw-r--r--Gemfile.lock10
-rw-r--r--actionpack/CHANGELOG.md5
-rw-r--r--actionpack/lib/action_controller/metal/helpers.rb4
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/response.rb4
-rw-r--r--actionpack/lib/action_dispatch/journey/router.rb2
-rw-r--r--actionpack/lib/action_dispatch/journey/routes.rb19
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb30
-rw-r--r--actionpack/lib/action_dispatch/testing/test_response.rb2
-rw-r--r--actionpack/test/abstract_unit.rb4
-rw-r--r--actionpack/test/controller/live_stream_test.rb2
-rw-r--r--actionpack/test/dispatch/debug_exceptions_test.rb4
-rw-r--r--actionpack/test/dispatch/response_test.rb2
-rw-r--r--actionpack/test/journey/routes_test.rb22
-rw-r--r--actionview/test/activerecord/polymorphic_routes_test.rb2
-rw-r--r--activemodel/lib/active_model.rb1
-rw-r--r--activemodel/lib/active_model/attribute_assignment.rb11
-rw-r--r--activemodel/lib/active_model/errors.rb11
-rw-r--r--activemodel/test/cases/attribute_assignment_test.rb6
-rw-r--r--activemodel/test/cases/helper.rb9
-rw-r--r--activemodel/test/cases/model_test.rb2
-rw-r--r--activerecord/lib/active_record/associations/collection_association.rb6
-rw-r--r--activerecord/lib/active_record/associations/collection_proxy.rb4
-rw-r--r--activerecord/lib/active_record/attribute_assignment.rb7
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/transaction.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb4
-rw-r--r--activerecord/lib/active_record/errors.rb6
-rw-r--r--activerecord/lib/active_record/fixtures.rb8
-rw-r--r--activerecord/lib/active_record/persistence.rb3
-rw-r--r--activerecord/lib/active_record/transactions.rb17
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb13
-rw-r--r--activerecord/test/cases/associations/has_one_associations_test.rb2
-rw-r--r--activerecord/test/cases/attribute_methods_test.rb6
-rw-r--r--activerecord/test/cases/attributes_test.rb2
-rw-r--r--activerecord/test/cases/fixtures_test.rb2
-rw-r--r--activerecord/test/cases/migration/create_join_table_test.rb2
-rw-r--r--activerecord/test/cases/migrator_test.rb2
-rw-r--r--activerecord/test/cases/nested_attributes_test.rb2
-rw-r--r--activerecord/test/schema/mysql2_specific_schema.rb8
-rw-r--r--activerecord/test/schema/mysql_specific_schema.rb8
-rw-r--r--activesupport/lib/active_support/core_ext/array/access.rb12
-rw-r--r--activesupport/lib/active_support/core_ext/array/grouping.rb12
-rw-r--r--activesupport/lib/active_support/rescuable.rb2
-rw-r--r--activesupport/test/caching_test.rb2
-rw-r--r--activesupport/test/core_ext/array/access_test.rb4
-rw-r--r--activesupport/test/core_ext/object/duplicable_test.rb3
-rw-r--r--activesupport/test/json/encoding_test.rb2
-rw-r--r--railties/lib/rails/engine.rb2
-rw-r--r--railties/lib/rails/ruby_version_check.rb2
-rw-r--r--railties/lib/rails/tasks/restart.rake2
52 files changed, 190 insertions, 114 deletions
diff --git a/Gemfile b/Gemfile
index 074db1b4eb..25850ff34e 100644
--- a/Gemfile
+++ b/Gemfile
@@ -15,6 +15,7 @@ gem 'jquery-rails', github: 'rails/jquery-rails', branch: 'master'
gem 'coffee-rails', '~> 4.1.0'
gem 'turbolinks'
gem 'arel', github: 'rails/arel', branch: 'master'
+gem 'mail', github: 'mikel/mail'
# require: false so bcrypt is loaded only when has_secure_password is used.
# This is to avoid ActiveModel (and by extension the entire framework)
diff --git a/Gemfile.lock b/Gemfile.lock
index 4fc36bf86c..e34449a7b0 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -12,6 +12,13 @@ GIT
redis-namespace
GIT
+ remote: git://github.com/mikel/mail.git
+ revision: b159e0a542962fdd5e292a48cfffa560d7cf412e
+ specs:
+ mail (2.6.3.edge)
+ mime-types (>= 1.16, < 3)
+
+GIT
remote: git://github.com/rails/arel.git
revision: aac9da257f291ad8d2d4f914528881c240848bb2
branch: master
@@ -123,8 +130,6 @@ GEM
nokogiri
loofah (2.0.1)
nokogiri (>= 1.5.9)
- mail (2.6.3)
- mime-types (>= 1.16, < 3)
metaclass (0.0.4)
mime-types (2.4.3)
mini_portile (0.6.2)
@@ -250,6 +255,7 @@ DEPENDENCIES
jquery-rails!
json
kindlerb (= 0.1.1)
+ mail!
minitest (< 5.3.4)
mocha (~> 0.14)
mysql (>= 2.9.0)
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 0134bf7cab..8c4ba2a154 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,3 +1,8 @@
+* Partitioning of routes is now done when the routes are being drawn. This
+ helps to decrease the time spent filtering the routes during the first request.
+
+ *Guo Xiang Tan*
+
* Fix regression in functional tests. Responses should have default headers
assigned.
diff --git a/actionpack/lib/action_controller/metal/helpers.rb b/actionpack/lib/action_controller/metal/helpers.rb
index a9c3e438fb..819837e767 100644
--- a/actionpack/lib/action_controller/metal/helpers.rb
+++ b/actionpack/lib/action_controller/metal/helpers.rb
@@ -93,6 +93,10 @@ module ActionController
super(args)
end
+ # Return a list of helper names in specific path.
+ #
+ # ActionController::Base.all_helpers_from_path 'app/helpers'
+ # # => ["application", "chart", "rubygems"]
def all_helpers_from_path(path)
helpers = Array(path).flat_map do |_path|
extract = /^#{Regexp.quote(_path.to_s)}\/?(.*)_helper.rb$/
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 07b3814ca4..732ee67268 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -114,7 +114,7 @@ module ActionDispatch
end
def engine_script_name(_routes) # :nodoc:
- env["ROUTES_#{_routes.object_id}_SCRIPT_NAME"]
+ env[_routes.env_key]
end
def request_method=(request_method) #:nodoc:
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index a895d1ab18..5fe544c60c 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -113,7 +113,9 @@ module ActionDispatch # :nodoc:
# The underlying body, as a streamable object.
attr_reader :stream
- def initialize(status = 200, header = {}, body = [], default_headers: self.class.default_headers)
+ # Ruby 2.2 bug https://bugs.ruby-lang.org/issues/10685 prevents
+ # default_headers from being a keyword argument.
+ def initialize(status = 200, header = {}, body = [], default_headers = self.class.default_headers)
super()
header = merge_default_headers(header, default_headers)
diff --git a/actionpack/lib/action_dispatch/journey/router.rb b/actionpack/lib/action_dispatch/journey/router.rb
index 2b036796ab..cc4bd6105d 100644
--- a/actionpack/lib/action_dispatch/journey/router.rb
+++ b/actionpack/lib/action_dispatch/journey/router.rb
@@ -88,7 +88,7 @@ module ActionDispatch
end
def custom_routes
- partitioned_routes.last
+ routes.custom_routes
end
def filter_routes(path)
diff --git a/actionpack/lib/action_dispatch/journey/routes.rb b/actionpack/lib/action_dispatch/journey/routes.rb
index 80e3818ccd..a6d1980db2 100644
--- a/actionpack/lib/action_dispatch/journey/routes.rb
+++ b/actionpack/lib/action_dispatch/journey/routes.rb
@@ -5,13 +5,14 @@ module ActionDispatch
class Routes # :nodoc:
include Enumerable
- attr_reader :routes, :named_routes
+ attr_reader :routes, :named_routes, :custom_routes, :anchored_routes
def initialize
@routes = []
@named_routes = {}
@ast = nil
- @partitioned_routes = nil
+ @anchored_routes = []
+ @custom_routes = []
@simulator = nil
end
@@ -30,18 +31,22 @@ module ActionDispatch
def clear
routes.clear
+ anchored_routes.clear
+ custom_routes.clear
named_routes.clear
end
- def partitioned_routes
- @partitioned_routes ||= routes.partition do |r|
- r.path.anchored && r.ast.grep(Nodes::Symbol).all?(&:default_regexp?)
+ def partition_route(route)
+ if route.path.anchored && route.ast.grep(Nodes::Symbol).all?(&:default_regexp?)
+ anchored_routes << route
+ else
+ custom_routes << route
end
end
def ast
@ast ||= begin
- asts = partitioned_routes.first.map(&:ast)
+ asts = anchored_routes.map(&:ast)
Nodes::Or.new(asts) unless asts.empty?
end
end
@@ -60,6 +65,7 @@ module ActionDispatch
route.precedence = routes.length
routes << route
named_routes[name] = route if name && !named_routes[name]
+ partition_route(route)
clear_cache!
route
end
@@ -68,7 +74,6 @@ module ActionDispatch
def clear_cache!
@ast = nil
- @partitioned_routes = nil
@simulator = nil
end
end
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index ce04f0b08a..58b3fff9d7 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -199,12 +199,9 @@ module ActionDispatch
private
def optimized_helper(args)
- params = parameterize_args(args)
- missing_keys = missing_keys(params)
-
- unless missing_keys.empty?
- raise_generation_error(params, missing_keys)
- end
+ params = parameterize_args(args) { |k|
+ raise_generation_error(args)
+ }
@route.format params
end
@@ -215,16 +212,21 @@ module ActionDispatch
def parameterize_args(args)
params = {}
- @required_parts.zip(args.map(&:to_param)) { |k,v| params[k] = v }
+ @arg_size.times { |i|
+ key = @required_parts[i]
+ value = args[i].to_param
+ yield key if value.nil? || value.empty?
+ params[key] = value
+ }
params
end
- def missing_keys(args)
- args.select{ |part, arg| arg.nil? || arg.empty? }.keys
- end
-
- def raise_generation_error(args, missing_keys)
- constraints = Hash[@route.requirements.merge(args).sort]
+ def raise_generation_error(args)
+ missing_keys = []
+ params = parameterize_args(args) { |missing_key|
+ missing_keys << missing_key
+ }
+ constraints = Hash[@route.requirements.merge(params).sort]
message = "No route matches #{constraints.inspect}"
message << " missing required keys: #{missing_keys.sort.inspect}"
@@ -308,6 +310,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, :request_class
+ attr_reader :env_key
alias :routes :set
@@ -325,6 +328,7 @@ module ActionDispatch
@prepend = []
@disable_clear_and_finalize = false
@finalized = false
+ @env_key = "ROUTES_#{object_id}_SCRIPT_NAME".freeze
@set = Journey::Routes.new
@router = Journey::Router.new @set
diff --git a/actionpack/lib/action_dispatch/testing/test_response.rb b/actionpack/lib/action_dispatch/testing/test_response.rb
index a9b88ac5fd..527784885c 100644
--- a/actionpack/lib/action_dispatch/testing/test_response.rb
+++ b/actionpack/lib/action_dispatch/testing/test_response.rb
@@ -7,7 +7,7 @@ module ActionDispatch
# See Response for more information on controller response objects.
class TestResponse < Response
def self.from_response(response)
- new response.status, response.headers, response.body, default_headers: nil
+ new response.status, response.headers, response.body, nil
end
# Was the response successful?
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index 918589f916..f5dd9d76af 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -95,7 +95,7 @@ end
module ActiveSupport
class TestCase
include ActionDispatch::DrawOnce
- if ActiveSupport::Testing::Isolation.forking_env? && PROCESS_COUNT > 0
+ if RUBY_ENGINE == "ruby" && PROCESS_COUNT > 0
parallelize_me!
end
end
@@ -479,7 +479,7 @@ class ForkingExecutor
end
end
-if ActiveSupport::Testing::Isolation.forking_env? && PROCESS_COUNT > 0
+if RUBY_ENGINE == "ruby" && PROCESS_COUNT > 0
# Use N processes (N defaults to 4)
Minitest.parallel_executor = ForkingExecutor.new(PROCESS_COUNT)
end
diff --git a/actionpack/test/controller/live_stream_test.rb b/actionpack/test/controller/live_stream_test.rb
index 7fd1276e98..0c65270ec1 100644
--- a/actionpack/test/controller/live_stream_test.rb
+++ b/actionpack/test/controller/live_stream_test.rb
@@ -276,6 +276,8 @@ module ActionController
end
def test_async_stream
+ rubinius_skip "https://github.com/rubinius/rubinius/issues/2934"
+
@controller.latch = ActiveSupport::Concurrency::Latch.new
parts = ['hello', 'world']
diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb
index 7921f05688..a867aee7ec 100644
--- a/actionpack/test/dispatch/debug_exceptions_test.rb
+++ b/actionpack/test/dispatch/debug_exceptions_test.rb
@@ -305,7 +305,7 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
assert_response 500
assert_select '#Application-Trace' do
- assert_select 'pre code', /\(eval\):1: syntax error, unexpected/
+ assert_select 'pre code', /syntax error, unexpected/
end
end
@@ -332,7 +332,7 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
assert_response 500
assert_select '#Application-Trace' do
- assert_select 'pre code', /\(eval\):1: syntax error, unexpected/
+ assert_select 'pre code', /syntax error, unexpected/
end
end
diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb
index f4c0b421d6..c61423dce4 100644
--- a/actionpack/test/dispatch/response_test.rb
+++ b/actionpack/test/dispatch/response_test.rb
@@ -172,7 +172,7 @@ class ResponseTest < ActiveSupport::TestCase
original = ActionDispatch::Response.default_charset
begin
ActionDispatch::Response.default_charset = 'utf-16'
- resp = ActionDispatch::Response.new(200, { "Content-Type" => "text/xml" }, default_headers: nil)
+ resp = ActionDispatch::Response.new(200, { "Content-Type" => "text/xml" })
assert_equal('utf-16', resp.charset)
ensure
ActionDispatch::Response.default_charset = original
diff --git a/actionpack/test/journey/routes_test.rb b/actionpack/test/journey/routes_test.rb
index a4efc82b8c..b54d961f66 100644
--- a/actionpack/test/journey/routes_test.rb
+++ b/actionpack/test/journey/routes_test.rb
@@ -3,6 +3,10 @@ require 'abstract_unit'
module ActionDispatch
module Journey
class TestRoutes < ActiveSupport::TestCase
+ setup do
+ @routes = Routes.new
+ end
+
def test_clear
routes = Routes.new
exp = Router::Strexp.build '/foo(/:id)', {}, ['/.?']
@@ -36,8 +40,24 @@ module ActionDispatch
assert_not_equal sim, routes.simulator
end
+ def test_partition_route
+ path = Path::Pattern.from_string '/hello'
+
+ anchored_route = @routes.add_route nil, path, {}, {}, {}
+ assert_equal [anchored_route], @routes.anchored_routes
+ assert_equal [], @routes.custom_routes
+
+ strexp = Router::Strexp.build(
+ "/hello/:who", { who: /\d/ }, ['/', '.', '?']
+ )
+ path = Path::Pattern.new strexp
+
+ custom_route = @routes.add_route nil, path, {}, {}, {}
+ assert_equal [custom_route], @routes.custom_routes
+ assert_equal [anchored_route], @routes.anchored_routes
+ end
+
def test_first_name_wins
- #def add_route app, path, conditions, defaults, name = nil
routes = Routes.new
one = Path::Pattern.from_string '/hello'
diff --git a/actionview/test/activerecord/polymorphic_routes_test.rb b/actionview/test/activerecord/polymorphic_routes_test.rb
index 6b51775cf3..34b2698c7f 100644
--- a/actionview/test/activerecord/polymorphic_routes_test.rb
+++ b/actionview/test/activerecord/polymorphic_routes_test.rb
@@ -208,7 +208,7 @@ class PolymorphicRoutesTest < ActionController::TestCase
@series.save
polymorphic_url([nil, @series])
end
- assert_match(/undefined method `series_url' for/, exception.message)
+ assert_match(/undefined method `series_url'/, exception.message)
end
end
diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb
index 58fe08cc11..8aa1b6f664 100644
--- a/activemodel/lib/active_model.rb
+++ b/activemodel/lib/active_model.rb
@@ -50,6 +50,7 @@ module ActiveModel
eager_autoload do
autoload :Errors
autoload :StrictValidationFailed, 'active_model/errors'
+ autoload :UnknownAttributeError, 'active_model/errors'
end
module Serializers
diff --git a/activemodel/lib/active_model/attribute_assignment.rb b/activemodel/lib/active_model/attribute_assignment.rb
index 356421476c..087d11f708 100644
--- a/activemodel/lib/active_model/attribute_assignment.rb
+++ b/activemodel/lib/active_model/attribute_assignment.rb
@@ -48,16 +48,5 @@ module ActiveModel
raise UnknownAttributeError.new(self, k)
end
end
-
- # Raised when unknown attributes are supplied via mass assignment.
- class UnknownAttributeError < NoMethodError
- attr_reader :record, :attribute
-
- def initialize(record, attribute)
- @record = record
- @attribute = attribute
- super("unknown attribute '#{attribute}' for #{@record.class}.")
- end
- end
end
end
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index 8326853879..f324788979 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -524,4 +524,15 @@ module ActiveModel
# # => ActiveModel::StrictValidationFailed: Name can't be blank
class StrictValidationFailed < StandardError
end
+
+ # Raised when unknown attributes are supplied via mass assignment.
+ class UnknownAttributeError < NoMethodError
+ attr_reader :record, :attribute
+
+ def initialize(record, attribute)
+ @record = record
+ @attribute = attribute
+ super("unknown attribute '#{attribute}' for #{@record.class}.")
+ end
+ end
end
diff --git a/activemodel/test/cases/attribute_assignment_test.rb b/activemodel/test/cases/attribute_assignment_test.rb
index 402caf21f7..3b01644dd1 100644
--- a/activemodel/test/cases/attribute_assignment_test.rb
+++ b/activemodel/test/cases/attribute_assignment_test.rb
@@ -49,7 +49,7 @@ class AttributeAssignmentTest < ActiveModel::TestCase
test "assign non-existing attribute" do
model = Model.new
- error = assert_raises(ActiveModel::AttributeAssignment::UnknownAttributeError) do
+ error = assert_raises(ActiveModel::UnknownAttributeError) do
model.assign_attributes(hz: 1)
end
@@ -58,8 +58,10 @@ class AttributeAssignmentTest < ActiveModel::TestCase
end
test "assign private attribute" do
+ rubinius_skip "https://github.com/rubinius/rubinius/issues/3328"
+
model = Model.new
- assert_raises(ActiveModel::AttributeAssignment::UnknownAttributeError) do
+ assert_raises(ActiveModel::UnknownAttributeError) do
model.assign_attributes(metadata: { a: 1 })
end
end
diff --git a/activemodel/test/cases/helper.rb b/activemodel/test/cases/helper.rb
index 4ce6103593..3276f69f09 100644
--- a/activemodel/test/cases/helper.rb
+++ b/activemodel/test/cases/helper.rb
@@ -14,6 +14,15 @@ require 'active_support/testing/autorun'
require 'mocha/setup' # FIXME: stop using mocha
+# Skips the current run on Rubinius using Minitest::Assertions#skip
+def rubinius_skip(message = '')
+ skip message if RUBY_ENGINE == 'rbx'
+end
+# Skips the current run on JRuby using Minitest::Assertions#skip
+def jruby_skip(message = '')
+ skip message if defined?(JRUBY_VERSION)
+end
+
# FIXME: we have tests that depend on run order, we should fix that and
# remove this method call.
require 'active_support/test_case'
diff --git a/activemodel/test/cases/model_test.rb b/activemodel/test/cases/model_test.rb
index 9a8d873ec9..3017f3541b 100644
--- a/activemodel/test/cases/model_test.rb
+++ b/activemodel/test/cases/model_test.rb
@@ -70,7 +70,7 @@ class ModelTest < ActiveModel::TestCase
end
def test_mixin_initializer_when_args_dont_exist
- assert_raises(ActiveModel::AttributeAssignment::UnknownAttributeError) do
+ assert_raises(ActiveModel::UnknownAttributeError) do
SimpleModel.new(hello: 'world')
end
end
diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb
index 82a7c27799..0ba03338f6 100644
--- a/activerecord/lib/active_record/associations/collection_association.rb
+++ b/activerecord/lib/active_record/associations/collection_association.rb
@@ -129,11 +129,11 @@ module ActiveRecord
first_nth_or_last(:last, *args)
end
- def take
+ def take(n = nil)
if loaded?
- target.first
+ n ? target.take(n) : target.first
else
- scope.take.tap do |record|
+ scope.take(n).tap do |record|
set_inverse_instance record if record.is_a? ActiveRecord::Base
end
end
diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb
index 87e80e88b2..e11c9490b7 100644
--- a/activerecord/lib/active_record/associations/collection_proxy.rb
+++ b/activerecord/lib/active_record/associations/collection_proxy.rb
@@ -227,8 +227,8 @@ module ActiveRecord
@association.last(*args)
end
- def take
- @association.take
+ def take(n = nil)
+ @association.take(n)
end
# Returns a new object of the collection type that has been instantiated
diff --git a/activerecord/lib/active_record/attribute_assignment.rb b/activerecord/lib/active_record/attribute_assignment.rb
index 483d4200bd..cc265e2af6 100644
--- a/activerecord/lib/active_record/attribute_assignment.rb
+++ b/activerecord/lib/active_record/attribute_assignment.rb
@@ -29,6 +29,13 @@ module ActiveRecord
assign_multiparameter_attributes(multi_parameter_attributes) unless multi_parameter_attributes.empty?
end
+ # Re-raise with the ActiveRecord constant in case of an error
+ def _assign_attribute(k, v) # :nodoc:
+ super
+ rescue ActiveModel::UnknownAttributeError
+ raise UnknownAttributeError.new(self, k)
+ end
+
# Assign any deferred nested attributes after the base attributes have been set.
def assign_nested_parameter_attributes(pairs)
pairs.each { |k, v| _assign_attribute(k, v) }
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
index 8c56ad12d8..a768ee2d70 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -401,7 +401,7 @@ module ActiveRecord
# Adds a reference. Optionally adds a +type+ column, if the
# +:polymorphic+ option is provided. +references+ and +belongs_to+
- # are acceptable. The reference column will be an +integer+ by default,
+ # are interchangeable. The reference column will be an +integer+ by default,
# the +:type+ option can be used to specify a different type. A foreign
# key will be created if the +:foreign_key+ option is passed.
#
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
index ebb4a1523f..c74f4e8fa5 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
@@ -24,7 +24,7 @@ module ActiveRecord
end
def set_state(state)
- if !VALID_STATES.include?(state)
+ unless VALID_STATES.include?(state)
raise ArgumentError, "Invalid transaction state: #{state}"
end
@state = state
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
index 75b9d079bd..eeb141dd1e 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
@@ -514,14 +514,14 @@ module ActiveRecord
sql = case type.to_s
when 'binary'
# PostgreSQL doesn't support limits on binary (bytea) columns.
- # The hard limit is 1Gb, because of a 32-bit size field, and TOAST.
+ # The hard limit is 1GB, because of a 32-bit size field, and TOAST.
case limit
when nil, 0..0x3fffffff; super(type)
else raise(ActiveRecordError, "No binary type has byte size #{limit}.")
end
when 'text'
# PostgreSQL doesn't support limits on text columns.
- # The hard limit is 1Gb, according to section 8.3 in the manual.
+ # The hard limit is 1GB, according to section 8.3 in the manual.
case limit
when nil, 0..0x3fffffff; super(type)
else raise(ActiveRecordError, "The limit on text can be at most 1GB - 1byte.")
diff --git a/activerecord/lib/active_record/errors.rb b/activerecord/lib/active_record/errors.rb
index d710d96a9a..98aee77557 100644
--- a/activerecord/lib/active_record/errors.rb
+++ b/activerecord/lib/active_record/errors.rb
@@ -178,10 +178,8 @@ module ActiveRecord
class DangerousAttributeError < ActiveRecordError
end
- UnknownAttributeError = ActiveSupport::Deprecation::DeprecatedConstantProxy.new( # :nodoc:
- 'ActiveRecord::UnknownAttributeError',
- 'ActiveModel::AttributeAssignment::UnknownAttributeError'
- )
+ # Raised when unknown attributes are supplied via mass assignment.
+ UnknownAttributeError = ActiveModel::UnknownAttributeError
# Raised when an error occurred while doing a mass assignment to an attribute through the
# +attributes=+ method. The exception has an +attribute+ property that is the name of the
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index 75b0e1e08d..18775caad2 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -539,12 +539,10 @@ module ActiveRecord
conn.insert_fixture(row, fixture_set_name)
end
end
- end
- # Cap primary key sequences to max(pk).
- if connection.respond_to?(:reset_pk_sequence!)
- fixture_sets.each do |fs|
- connection.reset_pk_sequence!(fs.table_name)
+ # Cap primary key sequences to max(pk).
+ if conn.respond_to?(:reset_pk_sequence!)
+ conn.reset_pk_sequence!(fs.table_name)
end
end
end
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index 7c076864a3..a6176dffdb 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -96,7 +96,8 @@ module ActiveRecord
# Returns true if the record is persisted, i.e. it's not a new record and it was
# not destroyed, otherwise returns false.
def persisted?
- !(new_record? || destroyed?)
+ sync_with_transaction_state
+ !(@new_record || @destroyed)
end
# Saves the model.
diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb
index b620233c3a..ffe7c4ae42 100644
--- a/activerecord/lib/active_record/transactions.rb
+++ b/activerecord/lib/active_record/transactions.rb
@@ -443,6 +443,8 @@ module ActiveRecord
end
end
+ private
+
def set_transaction_state(state) # :nodoc:
@transaction_state = state
end
@@ -469,18 +471,13 @@ module ActiveRecord
# method recursively goes through the parent of the TransactionState and
# checks if the ActiveRecord object reflects the state of the object.
def sync_with_transaction_state
- update_attributes_from_transaction_state(@transaction_state, 0)
+ update_attributes_from_transaction_state(@transaction_state)
end
- def update_attributes_from_transaction_state(transaction_state, depth)
- @reflects_state = [false] if depth == 0
-
- if transaction_state && transaction_state.finalized? && !has_transactional_callbacks?
- unless @reflects_state[depth]
- restore_transaction_record_state if transaction_state.rolledback?
- clear_transaction_record_state
- @reflects_state[depth] = true
- end
+ def update_attributes_from_transaction_state(transaction_state)
+ if transaction_state && transaction_state.finalized?
+ restore_transaction_record_state if transaction_state.rolledback?
+ clear_transaction_record_state
end
end
end
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index 897c52a49d..675bed9bfa 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -478,6 +478,19 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_raise(ActiveRecord::RecordNotFound) { authors(:bob).posts.take! }
end
+ def test_taking_with_a_number
+ # taking from unloaded Relation
+ bob = Author.find(authors(:bob).id)
+ assert_equal [posts(:misc_by_bob)], bob.posts.take(1)
+ bob = Author.find(authors(:bob).id)
+ assert_equal [posts(:misc_by_bob), posts(:other_by_bob)], bob.posts.take(2)
+
+ # taking from loaded Relation
+ bob.posts.to_a
+ assert_equal [posts(:misc_by_bob)], authors(:bob).posts.take(1)
+ assert_equal [posts(:misc_by_bob), posts(:other_by_bob)], authors(:bob).posts.take(2)
+ end
+
def test_taking_with_inverse_of
interests(:woodsmanship).destroy
interests(:survival).destroy
diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb
index 3b6a4038cd..7dc9266074 100644
--- a/activerecord/test/cases/associations/has_one_associations_test.rb
+++ b/activerecord/test/cases/associations/has_one_associations_test.rb
@@ -276,7 +276,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
def test_create_with_inexistent_foreign_key_failing
firm = Firm.create(name: 'GlobalMegaCorp')
- assert_raises(ActiveModel::AttributeAssignment::UnknownAttributeError) do
+ assert_raises(ActiveRecord::UnknownAttributeError) do
firm.create_account_with_inexistent_foreign_key
end
end
diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb
index 243c90e945..ea2b94cbf4 100644
--- a/activerecord/test/cases/attribute_methods_test.rb
+++ b/activerecord/test/cases/attribute_methods_test.rb
@@ -758,12 +758,12 @@ class AttributeMethodsTest < ActiveRecord::TestCase
def test_bulk_update_respects_access_control
privatize("title=(value)")
- assert_raise(ActiveModel::AttributeAssignment::UnknownAttributeError) { @target.new(:title => "Rants about pants") }
- assert_raise(ActiveModel::AttributeAssignment::UnknownAttributeError) { @target.new.attributes = { :title => "Ants in pants" } }
+ assert_raise(ActiveRecord::UnknownAttributeError) { @target.new(:title => "Rants about pants") }
+ assert_raise(ActiveRecord::UnknownAttributeError) { @target.new.attributes = { :title => "Ants in pants" } }
end
def test_bulk_update_raise_unknown_attribute_error
- error = assert_raises(ActiveModel::AttributeAssignment::UnknownAttributeError) {
+ error = assert_raises(ActiveRecord::UnknownAttributeError) {
Topic.new(hello: "world")
}
assert_instance_of Topic, error.record
diff --git a/activerecord/test/cases/attributes_test.rb b/activerecord/test/cases/attributes_test.rb
index e7b76b1cf9..927d7950a5 100644
--- a/activerecord/test/cases/attributes_test.rb
+++ b/activerecord/test/cases/attributes_test.rb
@@ -58,7 +58,7 @@ module ActiveRecord
data = OverloadedType.new(non_existent_decimal: 1)
assert_equal BigDecimal.new(1), data.non_existent_decimal
- assert_raise ActiveModel::AttributeAssignment::UnknownAttributeError do
+ assert_raise ActiveRecord::UnknownAttributeError do
UnoverloadedType.new(non_existent_decimal: 1)
end
end
diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index 7ef2ebc998..d1add21219 100644
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -327,7 +327,7 @@ if Account.connection.respond_to?(:reset_pk_sequence!)
fixtures :companies
def setup
- @instances = [Account.new(:credit_limit => 50), Company.new(:name => 'RoR Consulting')]
+ @instances = [Account.new(:credit_limit => 50), Company.new(:name => 'RoR Consulting'), Course.new(name: 'Test')]
ActiveRecord::FixtureSet.reset_cache # make sure tables get reinitialized
end
diff --git a/activerecord/test/cases/migration/create_join_table_test.rb b/activerecord/test/cases/migration/create_join_table_test.rb
index bea9d6b2c9..8fd08fe4ce 100644
--- a/activerecord/test/cases/migration/create_join_table_test.rb
+++ b/activerecord/test/cases/migration/create_join_table_test.rb
@@ -140,7 +140,7 @@ module ActiveRecord
tables_after = connection.tables - tables_before
tables_after.each do |table|
- connection.execute "DROP TABLE #{table}"
+ connection.drop_table table
end
end
end
diff --git a/activerecord/test/cases/migrator_test.rb b/activerecord/test/cases/migrator_test.rb
index c0daa83e9c..1760314099 100644
--- a/activerecord/test/cases/migrator_test.rb
+++ b/activerecord/test/cases/migrator_test.rb
@@ -312,7 +312,7 @@ class MigratorTest < ActiveRecord::TestCase
def test_migrator_db_has_no_schema_migrations_table
_, migrator = migrator_class(3)
- ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations")
+ ActiveRecord::Base.connection.drop_table "schema_migrations", if_exists: true
assert_not ActiveRecord::Base.connection.table_exists?('schema_migrations')
migrator.migrate("valid", 1)
assert ActiveRecord::Base.connection.table_exists?('schema_migrations')
diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb
index 198cd6f341..c5f6589c22 100644
--- a/activerecord/test/cases/nested_attributes_test.rb
+++ b/activerecord/test/cases/nested_attributes_test.rb
@@ -672,7 +672,7 @@ module NestedAttributesOnACollectionAssociationTests
end
def test_should_not_assign_destroy_key_to_a_record
- assert_nothing_raised ActiveModel::AttributeAssignment::UnknownAttributeError do
+ assert_nothing_raised ActiveRecord::UnknownAttributeError do
@pirate.send(association_setter, { 'foo' => { '_destroy' => '0' }})
end
end
diff --git a/activerecord/test/schema/mysql2_specific_schema.rb b/activerecord/test/schema/mysql2_specific_schema.rb
index a9a6514c9d..d6fd0c4ab0 100644
--- a/activerecord/test/schema/mysql2_specific_schema.rb
+++ b/activerecord/test/schema/mysql2_specific_schema.rb
@@ -35,9 +35,7 @@ BEGIN
END
SQL
- ActiveRecord::Base.connection.execute <<-SQL
-DROP TABLE IF EXISTS collation_tests;
-SQL
+ ActiveRecord::Base.connection.drop_table "collation_tests", if_exists: true
ActiveRecord::Base.connection.execute <<-SQL
CREATE TABLE collation_tests (
@@ -46,9 +44,7 @@ CREATE TABLE collation_tests (
) CHARACTER SET utf8 COLLATE utf8_general_ci
SQL
- ActiveRecord::Base.connection.execute <<-SQL
-DROP TABLE IF EXISTS enum_tests;
-SQL
+ ActiveRecord::Base.connection.drop_table "enum_tests", if_exists: true
ActiveRecord::Base.connection.execute <<-SQL
CREATE TABLE enum_tests (
diff --git a/activerecord/test/schema/mysql_specific_schema.rb b/activerecord/test/schema/mysql_specific_schema.rb
index f2cffca52c..b5378341b5 100644
--- a/activerecord/test/schema/mysql_specific_schema.rb
+++ b/activerecord/test/schema/mysql_specific_schema.rb
@@ -46,9 +46,7 @@ BEGIN
END
SQL
- ActiveRecord::Base.connection.execute <<-SQL
-DROP TABLE IF EXISTS collation_tests;
-SQL
+ ActiveRecord::Base.connection.drop_table "collation_tests", if_exists: true
ActiveRecord::Base.connection.execute <<-SQL
CREATE TABLE collation_tests (
@@ -57,9 +55,7 @@ CREATE TABLE collation_tests (
) CHARACTER SET utf8 COLLATE utf8_general_ci
SQL
- ActiveRecord::Base.connection.execute <<-SQL
-DROP TABLE IF EXISTS enum_tests;
-SQL
+ ActiveRecord::Base.connection.drop_table "enum_tests", if_exists: true
ActiveRecord::Base.connection.execute <<-SQL
CREATE TABLE enum_tests (
diff --git a/activesupport/lib/active_support/core_ext/array/access.rb b/activesupport/lib/active_support/core_ext/array/access.rb
index ca66d806ef..3177d8498e 100644
--- a/activesupport/lib/active_support/core_ext/array/access.rb
+++ b/activesupport/lib/active_support/core_ext/array/access.rb
@@ -27,6 +27,18 @@ class Array
end
end
+ # Returns a copy of the Array without the specified elements.
+ #
+ # people = ["David", "Rafael", "Aaron", "Todd"]
+ # people.without "Aaron", "Todd"
+ # => ["David", "Rafael"]
+ #
+ # Note: This is an optimization of `Enumerable#without` that uses `Array#-`
+ # instead of `Array#reject` for performance reasons.
+ def without(*elements)
+ self - elements
+ end
+
# Equal to <tt>self[1]</tt>.
#
# %w( a b c d e ).second # => "b"
diff --git a/activesupport/lib/active_support/core_ext/array/grouping.rb b/activesupport/lib/active_support/core_ext/array/grouping.rb
index b3ada47880..87ae052eb0 100644
--- a/activesupport/lib/active_support/core_ext/array/grouping.rb
+++ b/activesupport/lib/active_support/core_ext/array/grouping.rb
@@ -113,16 +113,4 @@ class Array
results
end
end
-
- # Returns a copy of the Array without the specified elements.
- #
- # people = ["David", "Rafael", "Aaron", "Todd"]
- # people.without "Aaron", "Todd"
- # => ["David", "Rafael"]
- #
- # Note: This is an optimization of `Enumerable#without` that uses `Array#-`
- # instead of `Array#reject` for performance reasons.
- def without(*elements)
- self - elements
- end
end
diff --git a/activesupport/lib/active_support/rescuable.rb b/activesupport/lib/active_support/rescuable.rb
index 1a02acd5b1..67aac32742 100644
--- a/activesupport/lib/active_support/rescuable.rb
+++ b/activesupport/lib/active_support/rescuable.rb
@@ -100,7 +100,7 @@ module ActiveSupport
# a string, otherwise a NameError will be raised by the interpreter
# itself when rescue_from CONSTANT is executed.
klass = self.class.const_get(klass_name) rescue nil
- klass ||= klass_name.constantize rescue nil
+ klass ||= (klass_name.constantize rescue nil)
klass === exception if klass
end
diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb
index d8f55f0525..7f5f8feb0d 100644
--- a/activesupport/test/caching_test.rb
+++ b/activesupport/test/caching_test.rb
@@ -1028,7 +1028,7 @@ class CacheStoreLoggerTest < ActiveSupport::TestCase
@cache.read_multi('hello', 'world')
- assert_match "Caches multi read:\n- hello\n- world", @buffer.string.tap { |l| l }
+ assert_match "Caches multi read:\n- hello\n- world", @buffer.string
end
end
diff --git a/activesupport/test/core_ext/array/access_test.rb b/activesupport/test/core_ext/array/access_test.rb
index f14f64421d..3f1e0c4cb4 100644
--- a/activesupport/test/core_ext/array/access_test.rb
+++ b/activesupport/test/core_ext/array/access_test.rb
@@ -27,4 +27,8 @@ class AccessTest < ActiveSupport::TestCase
assert_equal array[4], array.fifth
assert_equal array[41], array.forty_two
end
+
+ def test_without
+ assert_equal [1, 2, 4], [1, 2, 3, 4, 5].without(3, 5)
+ end
end
diff --git a/activesupport/test/core_ext/object/duplicable_test.rb b/activesupport/test/core_ext/object/duplicable_test.rb
index d37f4bd0d8..042f5cfb34 100644
--- a/activesupport/test/core_ext/object/duplicable_test.rb
+++ b/activesupport/test/core_ext/object/duplicable_test.rb
@@ -9,6 +9,9 @@ class DuplicableTest < ActiveSupport::TestCase
ALLOW_DUP << BigDecimal.new('4.56')
def test_duplicable
+ rubinius_skip "* Method#dup is allowed at the moment on Rubinius\n" \
+ "* https://github.com/rubinius/rubinius/issues/3089"
+
RAISE_DUP.each do |v|
assert !v.duplicable?
assert_raises(TypeError, v.class.name) { v.dup }
diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb
index 63d921e3b4..2f269a66f0 100644
--- a/activesupport/test/json/encoding_test.rb
+++ b/activesupport/test/json/encoding_test.rb
@@ -130,6 +130,8 @@ class TestJSONEncoding < ActiveSupport::TestCase
end
def test_process_status
+ rubinius_skip "https://github.com/rubinius/rubinius/issues/3334"
+
# There doesn't seem to be a good way to get a handle on a Process::Status object without actually
# creating a child process, hence this to populate $?
system("not_a_real_program_#{SecureRandom.hex}")
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index e1d5caf790..fd37fd0457 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -513,7 +513,7 @@ module Rails
def call(env)
env.merge!(env_config)
if env['SCRIPT_NAME']
- env["ROUTES_#{routes.object_id}_SCRIPT_NAME"] = env['SCRIPT_NAME'].dup
+ env[routes.env_key] = env['SCRIPT_NAME'].dup
end
app.call(env)
end
diff --git a/railties/lib/rails/ruby_version_check.rb b/railties/lib/rails/ruby_version_check.rb
index aea3d2339c..e2a199ec4d 100644
--- a/railties/lib/rails/ruby_version_check.rb
+++ b/railties/lib/rails/ruby_version_check.rb
@@ -1,4 +1,4 @@
-if RUBY_VERSION < '2.2.0'
+if RUBY_VERSION < '2.2.0' && RUBY_ENGINE == 'ruby'
desc = defined?(RUBY_DESCRIPTION) ? RUBY_DESCRIPTION : "ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE})"
abort <<-end_message
diff --git a/railties/lib/rails/tasks/restart.rake b/railties/lib/rails/tasks/restart.rake
index 1af0302824..1e8940b675 100644
--- a/railties/lib/rails/tasks/restart.rake
+++ b/railties/lib/rails/tasks/restart.rake
@@ -1,4 +1,4 @@
desc "Restart app by touching tmp/restart.txt"
-task restart: :environment do
+task :restart do
FileUtils.touch('tmp/restart.txt')
end