diff options
34 files changed, 292 insertions, 210 deletions
diff --git a/actionpack/lib/action_dispatch/middleware/public_exceptions.rb b/actionpack/lib/action_dispatch/middleware/public_exceptions.rb index 040cb215b7..7cde76b30e 100644 --- a/actionpack/lib/action_dispatch/middleware/public_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/public_exceptions.rb @@ -17,10 +17,10 @@ module ActionDispatch end def call(env) - status = env["PATH_INFO"][1..-1] + status = env["PATH_INFO"][1..-1].to_i request = ActionDispatch::Request.new(env) content_type = request.formats.first - body = { :status => status, :error => Rack::Utils::HTTP_STATUS_CODES.fetch(status.to_i, Rack::Utils::HTTP_STATUS_CODES[500]) } + body = { :status => status, :error => Rack::Utils::HTTP_STATUS_CODES.fetch(status, Rack::Utils::HTTP_STATUS_CODES[500]) } render(status, content_type, body) end diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb index 103ca9c776..efd790de63 100644 --- a/actionpack/test/controller/redirect_test.rb +++ b/actionpack/test/controller/redirect_test.rb @@ -63,7 +63,7 @@ class RedirectController < ActionController::Base end def redirect_to_url_with_unescaped_query_string - redirect_to "http://dev.rubyonrails.org/query?status=new" + redirect_to "http://example.com/query?status=new" end def redirect_to_url_with_complex_scheme @@ -233,7 +233,7 @@ class RedirectTest < ActionController::TestCase def test_redirect_to_url_with_unescaped_query_string get :redirect_to_url_with_unescaped_query_string assert_response :redirect - assert_redirected_to "http://dev.rubyonrails.org/query?status=new" + assert_redirected_to "http://example.com/query?status=new" end def test_redirect_to_url_with_complex_scheme diff --git a/actionpack/test/controller/show_exceptions_test.rb b/actionpack/test/controller/show_exceptions_test.rb index fba5ebba15..786dc15444 100644 --- a/actionpack/test/controller/show_exceptions_test.rb +++ b/actionpack/test/controller/show_exceptions_test.rb @@ -75,7 +75,7 @@ module ShowExceptions get "/", headers: { 'HTTP_ACCEPT' => 'application/json' } assert_response :internal_server_error assert_equal 'application/json', response.content_type.to_s - assert_equal({ :status => '500', :error => 'Internal Server Error' }.to_json, response.body) + assert_equal({ :status => 500, :error => 'Internal Server Error' }.to_json, response.body) end def test_render_xml_exception @@ -83,7 +83,7 @@ module ShowExceptions get "/", headers: { 'HTTP_ACCEPT' => 'application/xml' } assert_response :internal_server_error assert_equal 'application/xml', response.content_type.to_s - assert_equal({ :status => '500', :error => 'Internal Server Error' }.to_xml, response.body) + assert_equal({ :status => 500, :error => 'Internal Server Error' }.to_xml, response.body) end def test_render_fallback_exception diff --git a/actionview/lib/action_view/helpers/url_helper.rb b/actionview/lib/action_view/helpers/url_helper.rb index 4c436bce25..89b96ac42c 100644 --- a/actionview/lib/action_view/helpers/url_helper.rb +++ b/actionview/lib/action_view/helpers/url_helper.rb @@ -292,8 +292,9 @@ module ActionView form_method = method == 'get' ? 'get' : 'post' form_options = html_options.delete('form') || {} form_options[:class] ||= html_options.delete('form_class') || 'button_to' - form_options.merge!(method: form_method, action: url) - form_options.merge!("data-remote" => "true") if remote + form_options[:method] = form_method + form_options[:action] = url + form_options[:'data-remote'] = true if remote request_token_tag = form_method == 'post' ? token_tag : '' diff --git a/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb b/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb index e02593ec9c..743d5ea333 100644 --- a/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb +++ b/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb @@ -18,17 +18,19 @@ module ActiveJob def enqueue(job) #:nodoc: #Sidekiq::Client does not support symbols as keys Sidekiq::Client.push \ - 'class' => JobWrapper, - 'queue' => job.queue_name, - 'args' => [ job.serialize ] + 'class' => JobWrapper, + 'wrapped' => job.class.to_s, + 'queue' => job.queue_name, + 'args' => [ job.serialize ] end def enqueue_at(job, timestamp) #:nodoc: Sidekiq::Client.push \ - 'class' => JobWrapper, - 'queue' => job.queue_name, - 'args' => [ job.serialize ], - 'at' => timestamp + 'class' => JobWrapper, + 'wrapped' => job.class.to_s, + 'queue' => job.queue_name, + 'args' => [ job.serialize ], + 'at' => timestamp end class JobWrapper #:nodoc: diff --git a/activejob/test/integration/queuing_test.rb b/activejob/test/integration/queuing_test.rb index 38874b51a8..af19a92118 100644 --- a/activejob/test/integration/queuing_test.rb +++ b/activejob/test/integration/queuing_test.rb @@ -1,5 +1,6 @@ require 'helper' require 'jobs/logging_job' +require 'jobs/hello_job' require 'active_support/core_ext/numeric/time' class QueuingTest < ActiveSupport::TestCase @@ -23,6 +24,18 @@ class QueuingTest < ActiveSupport::TestCase end end + test 'should supply a wrapped class name to Sidekiq' do + skip unless adapter_is?(:sidekiq) + require 'sidekiq/testing' + + Sidekiq::Testing.fake! do + ::HelloJob.perform_later + hash = ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper.jobs.first + assert_equal "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper", hash['class'] + assert_equal "HelloJob", hash['wrapped'] + end + end + test 'should not run job enqueued in the future' do begin TestJob.set(wait: 10.minutes).perform_later @id diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb index cbca76d949..e35ed03e74 100644 --- a/activemodel/lib/active_model/errors.rb +++ b/activemodel/lib/active_model/errors.rb @@ -34,11 +34,11 @@ module ActiveModel # send(attr) # end # - # def Person.human_attribute_name(attr, options = {}) + # def self.human_attribute_name(attr, options = {}) # attr # end # - # def Person.lookup_ancestors + # def self.lookup_ancestors # [self] # end # end @@ -124,9 +124,9 @@ module ActiveModel # Set messages for +key+ to +value+. # - # person.errors.get(:name) # => ["cannot be nil"] + # person.errors[:name] # => ["cannot be nil"] # person.errors.set(:name, ["can't be nil"]) - # person.errors.get(:name) # => ["can't be nil"] + # person.errors[:name] # => ["can't be nil"] def set(key, value) ActiveSupport::Deprecation.warn(<<-MESSAGE.squish) ActiveModel::Errors#set is deprecated and will be removed in Rails 5.1. @@ -139,12 +139,12 @@ module ActiveModel # Delete messages for +key+. Returns the deleted messages. # - # person.errors.get(:name) # => ["cannot be nil"] + # person.errors[:name] # => ["cannot be nil"] # person.errors.delete(:name) # => ["cannot be nil"] - # person.errors.get(:name) # => [] + # person.errors[:name] # => [] def delete(key) - messages.delete(key) details.delete(key) + messages.delete(key) end # When passed a symbol or a name of a method, returns an array of errors diff --git a/activemodel/test/cases/errors_test.rb b/activemodel/test/cases/errors_test.rb index da142ea2c0..ddd003d53f 100644 --- a/activemodel/test/cases/errors_test.rb +++ b/activemodel/test/cases/errors_test.rb @@ -377,6 +377,12 @@ class ErrorsTest < ActiveModel::TestCase assert_empty errors.details[:name] end + test "delete returns the deleted messages" do + errors = ActiveModel::Errors.new(Person.new) + errors.add(:name, :invalid) + assert_equal ["is invalid"], errors.delete(:name) + end + test "clear removes details" do person = Person.new person.errors.add(:name, :invalid) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index b5ab5587f6..accf356a0c 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,10 +1,25 @@ -* Fix referencing wrong table aliases while joining tables of has many through association - (only when calling calculation methods). +* Fix referencing wrong table aliases while joining tables of has many through + association (only when calling calculation methods). - Fixes #19276 + Fixes #19276. *pinglamb* +* Correctly persist a serialized attribute that has been returned to + its default value by an in-place modification. + + Fixes #19467. + + *Matthew Draper* + +* Fix generating the schema file when using PostgreSQL `BigInt[]` data type. + Previously the `limit: 8` was not coming through, and this caused it to + become `Int[]` data type after rebuilding from the schema. + + Fixes #19420. + + *Jake Waller* + * Reuse the `CollectionAssociation#reader` cache when the foreign key is available prior to save. @@ -705,10 +720,4 @@ *Yves Senn* -* Fixes #19420. When generating schema.rb using Postgres BigInt[] data type - the limit: 8 was not coming through. This caused it to become Int[] data type - after doing a rebuild off of schema.rb. - - *Jake Waller* - Please check [4-2-stable](https://github.com/rails/rails/blob/4-2-stable/activerecord/CHANGELOG.md) for previous changes. diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index d42f9a894b..72e019066e 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -652,7 +652,7 @@ module ActiveRecord alias :add_belongs_to :add_reference # Removes the reference(s). Also removes a +type+ column if one exists. - # <tt>remove_reference</tt>, <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are acceptable. + # <tt>remove_reference</tt> and <tt>remove_belongs_to</tt> are acceptable. # # ====== Remove the reference # diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index b4e29a608a..b7c7ff1187 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -905,8 +905,7 @@ module ActiveRecord def configure_connection variables = @config.fetch(:variables, {}).stringify_keys - # By default, MySQL 'where id is null' selects the last inserted id. - # Turn this off. http://dev.rubyonrails.org/ticket/6778 + # By default, MySQL 'where id is null' selects the last inserted id; Turn this off. variables['sql_auto_is_null'] = 0 # Increase timeout so the server doesn't disconnect us. @@ -915,7 +914,7 @@ module ActiveRecord variables['wait_timeout'] = self.class.type_cast_config_to_integer(wait_timeout) # Make MySQL reject illegal values rather than truncating or blanking them, see - # http://dev.mysql.com/doc/refman/5.6/en/server-sql-mode.html#sqlmode_strict_all_tables + # http://dev.mysql.com/doc/refman/5.6/en/sql-mode.html#sqlmode_strict_all_tables # If the user has provided another value for sql_mode, don't replace it. unless variables.has_key?('sql_mode') variables['sql_mode'] = strict_mode? ? 'STRICT_ALL_TABLES' : '' diff --git a/activerecord/lib/active_record/type/serialized.rb b/activerecord/lib/active_record/type/serialized.rb index 732029c723..ea3e0d6a45 100644 --- a/activerecord/lib/active_record/type/serialized.rb +++ b/activerecord/lib/active_record/type/serialized.rb @@ -26,9 +26,15 @@ module ActiveRecord end end + def inspect + Kernel.instance_method(:inspect).bind(self).call + end + def changed_in_place?(raw_old_value, value) return false if value.nil? - subtype.changed_in_place?(raw_old_value, serialize(value)) + raw_new_value = serialize(value) + raw_old_value.nil? != raw_new_value.nil? || + subtype.changed_in_place?(raw_old_value, raw_new_value) end def accessor diff --git a/activerecord/test/cases/adapters/postgresql/infinity_test.rb b/activerecord/test/cases/adapters/postgresql/infinity_test.rb index 24199c69b8..d9d7832094 100644 --- a/activerecord/test/cases/adapters/postgresql/infinity_test.rb +++ b/activerecord/test/cases/adapters/postgresql/infinity_test.rb @@ -24,6 +24,15 @@ class PostgresqlInfinityTest < ActiveRecord::TestCase assert_equal Float::INFINITY, record.float end + test "type casting string on a float column" do + record = PostgresqlInfinity.new(float: 'Infinity') + assert_equal Float::INFINITY, record.float + record = PostgresqlInfinity.new(float: '-Infinity') + assert_equal(-Float::INFINITY, record.float) + record = PostgresqlInfinity.new(float: 'NaN') + assert_send [record.float, :nan?] + end + test "update_all with infinity on a float column" do record = PostgresqlInfinity.create! PostgresqlInfinity.update_all(float: Float::INFINITY) diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb index 39308866ee..4b819a82e8 100644 --- a/activerecord/test/cases/finder_test.rb +++ b/activerecord/test/cases/finder_test.rb @@ -947,7 +947,6 @@ class FinderTest < ActiveRecord::TestCase end end - # http://dev.rubyonrails.org/ticket/6778 def test_find_ignores_previously_inserted_record Post.create!(:title => 'test', :body => 'it out') assert_equal [], Post.where(id: nil) diff --git a/activerecord/test/cases/modules_test.rb b/activerecord/test/cases/modules_test.rb index 6f65bf80eb..7f31325f47 100644 --- a/activerecord/test/cases/modules_test.rb +++ b/activerecord/test/cases/modules_test.rb @@ -68,8 +68,7 @@ class ModulesTest < ActiveRecord::TestCase end end - # need to add an eager loading condition to force the eager loading model into - # the old join model, to test that. See http://dev.rubyonrails.org/ticket/9640 + # An eager loading condition to force the eager loading model into the old join model. def test_eager_loading_in_modules clients = [] diff --git a/activerecord/test/cases/serialized_attribute_test.rb b/activerecord/test/cases/serialized_attribute_test.rb index e29f7462c8..7c92453ee3 100644 --- a/activerecord/test/cases/serialized_attribute_test.rb +++ b/activerecord/test/cases/serialized_attribute_test.rb @@ -264,4 +264,14 @@ class SerializedAttributeTest < ActiveRecord::TestCase Topic.serialize(:content, Regexp) end end + + def test_newly_emptied_serialized_hash_is_changed + Topic.serialize(:content, Hash) + topic = Topic.create(content: { "things" => "stuff" }) + topic.content.delete("things") + topic.save! + topic.reload + + assert_equal({}, topic.content) + end end diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 43fb87f203..49088527ae 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,7 @@ +* Deprecate `alias_method_chain` in favour of `Module#prepend` introduced in Ruby 2.0 + + *Kir Shatrov* + * Added `#without` on `Enumerable` and `Array` to return a copy of an enumerable without the specified elements. diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb index 080e3b5ef7..d80df21e7d 100644 --- a/activesupport/lib/active_support/core_ext/array/conversions.rb +++ b/activesupport/lib/active_support/core_ext/array/conversions.rb @@ -74,7 +74,7 @@ class Array when 0 '' when 1 - self[0].to_s.dup + "#{self[0]}" when 2 "#{self[0]}#{options[:two_words_connector]}#{self[1]}" else diff --git a/activesupport/lib/active_support/core_ext/integer/time.rb b/activesupport/lib/active_support/core_ext/integer/time.rb index 82080ffe51..f0b7382ef3 100644 --- a/activesupport/lib/active_support/core_ext/integer/time.rb +++ b/activesupport/lib/active_support/core_ext/integer/time.rb @@ -17,21 +17,6 @@ class Integer # # # equivalent to Time.now.advance(months: 4, years: 5) # (4.months + 5.years).from_now - # - # While these methods provide precise calculation when used as in the examples - # above, care should be taken to note that this is not true if the result of - # +months+, +years+, etc is converted before use: - # - # # equivalent to 30.days.to_i.from_now - # 1.month.to_i.from_now - # - # # equivalent to 365.25.days.to_f.from_now - # 1.year.to_f.from_now - # - # In such cases, Ruby's core - # Date[http://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html] and - # Time[http://ruby-doc.org/stdlib/libdoc/time/rdoc/Time.html] should be used for precision - # date and time arithmetic. def months ActiveSupport::Duration.new(self * 30.days, [[:months, self]]) end diff --git a/activesupport/lib/active_support/core_ext/module/aliasing.rb b/activesupport/lib/active_support/core_ext/module/aliasing.rb index 0a6fadf928..25e138264e 100644 --- a/activesupport/lib/active_support/core_ext/module/aliasing.rb +++ b/activesupport/lib/active_support/core_ext/module/aliasing.rb @@ -21,6 +21,8 @@ class Module # # so you can safely chain foo, foo?, foo! and/or foo= with the same feature. def alias_method_chain(target, feature) + ActiveSupport::Deprecation.warn("alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super.") + # Strip out punctuation on predicates, bang or writer methods since # e.g. target?_without_feature is not a valid method name. aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1 diff --git a/activesupport/lib/active_support/core_ext/numeric/time.rb b/activesupport/lib/active_support/core_ext/numeric/time.rb index 98716383f4..6c4a975495 100644 --- a/activesupport/lib/active_support/core_ext/numeric/time.rb +++ b/activesupport/lib/active_support/core_ext/numeric/time.rb @@ -18,21 +18,6 @@ class Numeric # # # equivalent to Time.current.advance(months: 4, years: 5) # (4.months + 5.years).from_now - # - # While these methods provide precise calculation when used as in the examples above, care - # should be taken to note that this is not true if the result of `months', `years', etc is - # converted before use: - # - # # equivalent to 30.days.to_i.from_now - # 1.month.to_i.from_now - # - # # equivalent to 365.25.days.to_f.from_now - # 1.year.to_f.from_now - # - # In such cases, Ruby's core - # Date[http://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html] and - # Time[http://ruby-doc.org/stdlib/libdoc/time/rdoc/Time.html] should be used for precision - # date and time arithmetic. def seconds ActiveSupport::Duration.new(self, [[:seconds, self]]) end diff --git a/activesupport/lib/active_support/core_ext/range/each.rb b/activesupport/lib/active_support/core_ext/range/each.rb index ecef78f55f..f666480fe6 100644 --- a/activesupport/lib/active_support/core_ext/range/each.rb +++ b/activesupport/lib/active_support/core_ext/range/each.rb @@ -1,18 +1,22 @@ -require 'active_support/core_ext/module/aliasing' - class Range #:nodoc: def each_with_time_with_zone(&block) ensure_iteration_allowed each_without_time_with_zone(&block) end - alias_method_chain :each, :time_with_zone + # TODO: change to Module#prepend as soon as the fix is backported to MRI 2.2: + # https://bugs.ruby-lang.org/issues/10847 + alias_method :each_without_time_with_zone, :each + alias_method :each, :each_with_time_with_zone def step_with_time_with_zone(n = 1, &block) ensure_iteration_allowed step_without_time_with_zone(n, &block) end - alias_method_chain :step, :time_with_zone + # TODO: change to Module#prepend as soon as the fix is backported to MRI 2.2: + # https://bugs.ruby-lang.org/issues/10847 + alias_method :step_without_time_with_zone, :step + alias_method :step, :step_with_time_with_zone private def ensure_iteration_allowed diff --git a/activesupport/lib/active_support/core_ext/range/include_range.rb b/activesupport/lib/active_support/core_ext/range/include_range.rb index 3a07401c8a..9d20920dd0 100644 --- a/activesupport/lib/active_support/core_ext/range/include_range.rb +++ b/activesupport/lib/active_support/core_ext/range/include_range.rb @@ -1,5 +1,3 @@ -require 'active_support/core_ext/module/aliasing' - class Range # Extends the default Range#include? to support range comparisons. # (1..5).include?(1..5) # => true @@ -18,6 +16,8 @@ class Range include_without_range?(value) end end - - alias_method_chain :include?, :range + # TODO: change to Module#prepend as soon as the fix is backported to MRI 2.2: + # https://bugs.ruby-lang.org/issues/10847 + alias_method :include_without_range?, :include? + alias_method :include?, :include_with_range? end diff --git a/activesupport/lib/active_support/deprecation/method_wrappers.rb b/activesupport/lib/active_support/deprecation/method_wrappers.rb index cab8a1b14d..c74e9c40ac 100644 --- a/activesupport/lib/active_support/deprecation/method_wrappers.rb +++ b/activesupport/lib/active_support/deprecation/method_wrappers.rb @@ -31,12 +31,14 @@ module ActiveSupport method_names += options.keys method_names.each do |method_name| - target_module.alias_method_chain(method_name, :deprecation) do |target, punctuation| - target_module.send(:define_method, "#{target}_with_deprecation#{punctuation}") do |*args, &block| + mod = Module.new do + define_method(method_name) do |*args, &block| deprecator.deprecation_warning(method_name, options[method_name]) - send(:"#{target}_without_deprecation#{punctuation}", *args, &block) + super(*args, &block) end end + + target_module.prepend(mod) end end end diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb index 5a64fc52cc..4c0d1197fe 100644 --- a/activesupport/lib/active_support/duration.rb +++ b/activesupport/lib/active_support/duration.rb @@ -56,6 +56,30 @@ module ActiveSupport @value.to_s end + # Returns the number of seconds that this Duration represents. + # + # 1.minute.to_i # => 60 + # 1.hour.to_i # => 3600 + # 1.day.to_i # => 86400 + # + # Note that this conversion makes some assumptions about the + # duration of some periods, e.g. months are always 30 days + # and years are 365.25 days: + # + # # equivalent to 30.days.to_i + # 1.month.to_i # => 2592000 + # + # # equivalent to 365.25.days.to_i + # 1.year.to_i # => 31557600 + # + # In such cases, Ruby's core + # Date[http://ruby-doc.org/stdlib/libdoc/date/rdoc/Date.html] and + # Time[http://ruby-doc.org/stdlib/libdoc/time/rdoc/Time.html] should be used for precision + # date and time arithmetic. + def to_i + @value.to_i + end + # Returns +true+ if +other+ is also a Duration instance, which has the # same parts as this one. def eql?(other) diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb index 739823bd56..24b8f4b9f9 100644 --- a/activesupport/lib/active_support/test_case.rb +++ b/activesupport/lib/active_support/test_case.rb @@ -45,8 +45,6 @@ module ActiveSupport test_order end - - alias :my_tests_are_order_dependent! :i_suck_and_my_tests_are_order_dependent! end alias_method :method_name, :name @@ -75,7 +73,7 @@ module ActiveSupport alias :assert_not_respond_to :refute_respond_to alias :assert_not_same :refute_same - # Fails if the block raises an exception. + # Reveals the intention that the block should not raise any exception. # # assert_nothing_raised do # ... diff --git a/activesupport/lib/active_support/testing/time_helpers.rb b/activesupport/lib/active_support/testing/time_helpers.rb index c9d20cd837..3478b09423 100644 --- a/activesupport/lib/active_support/testing/time_helpers.rb +++ b/activesupport/lib/active_support/testing/time_helpers.rb @@ -39,7 +39,7 @@ module ActiveSupport end end - # Containing helpers that helps you test passage of time. + # Contain helpers that help you test passage of time. module TimeHelpers # Changes current time to the time in the future or in the past by a given time difference by # stubbing +Time.now+, +Date.today+, and +DateTime.now+. diff --git a/activesupport/test/core_ext/array/conversions_test.rb b/activesupport/test/core_ext/array/conversions_test.rb index 577b889410..507e13f968 100644 --- a/activesupport/test/core_ext/array/conversions_test.rb +++ b/activesupport/test/core_ext/array/conversions_test.rb @@ -60,6 +60,12 @@ class ToSentenceTest < ActiveSupport::TestCase assert_equal exception.message, "Unknown key: :passing. Valid keys are: :words_connector, :two_words_connector, :last_word_connector, :locale" end + + def test_always_returns_string + assert_instance_of String, [ActiveSupport::SafeBuffer.new('one')].to_sentence + assert_instance_of String, [ActiveSupport::SafeBuffer.new('one'), 'two'].to_sentence + assert_instance_of String, [ActiveSupport::SafeBuffer.new('one'), 'two', 'three'].to_sentence + end end class ToSTest < ActiveSupport::TestCase diff --git a/activesupport/test/core_ext/module_test.rb b/activesupport/test/core_ext/module_test.rb index c9c9b66a6c..bdfbadcf1d 100644 --- a/activesupport/test/core_ext/module_test.rb +++ b/activesupport/test/core_ext/module_test.rb @@ -358,148 +358,178 @@ class MethodAliasingTest < ActiveSupport::TestCase Object.instance_eval { remove_const :FooClassWithBarMethod } end - def test_alias_method_chain - assert @instance.respond_to?(:bar) - feature_aliases = [:bar_with_baz, :bar_without_baz] + def test_alias_method_chain_deprecated + assert_deprecated(/alias_method_chain/) do + Module.new do + def base + end + + def base_with_deprecated + end - feature_aliases.each do |method| - assert !@instance.respond_to?(method) + alias_method_chain :base, :deprecated + end end + end - assert_equal 'bar', @instance.bar + def test_alias_method_chain + assert_deprecated(/alias_method_chain/) do + assert @instance.respond_to?(:bar) + feature_aliases = [:bar_with_baz, :bar_without_baz] - FooClassWithBarMethod.class_eval { include BarMethodAliaser } + feature_aliases.each do |method| + assert !@instance.respond_to?(method) + end - feature_aliases.each do |method| - assert_respond_to @instance, method - end + assert_equal 'bar', @instance.bar + + FooClassWithBarMethod.class_eval { include BarMethodAliaser } + + feature_aliases.each do |method| + assert_respond_to @instance, method + end - assert_equal 'bar_with_baz', @instance.bar - assert_equal 'bar', @instance.bar_without_baz + assert_equal 'bar_with_baz', @instance.bar + assert_equal 'bar', @instance.bar_without_baz + end end def test_alias_method_chain_with_punctuation_method - FooClassWithBarMethod.class_eval do - def quux!; 'quux' end - end + assert_deprecated(/alias_method_chain/) do + FooClassWithBarMethod.class_eval do + def quux!; 'quux' end + end - assert !@instance.respond_to?(:quux_with_baz!) - FooClassWithBarMethod.class_eval do - include BarMethodAliaser - alias_method_chain :quux!, :baz - end - assert_respond_to @instance, :quux_with_baz! + assert !@instance.respond_to?(:quux_with_baz!) + FooClassWithBarMethod.class_eval do + include BarMethodAliaser + alias_method_chain :quux!, :baz + end + assert_respond_to @instance, :quux_with_baz! - assert_equal 'quux_with_baz', @instance.quux! - assert_equal 'quux', @instance.quux_without_baz! + assert_equal 'quux_with_baz', @instance.quux! + assert_equal 'quux', @instance.quux_without_baz! + end end def test_alias_method_chain_with_same_names_between_predicates_and_bang_methods - FooClassWithBarMethod.class_eval do - def quux!; 'quux!' end - def quux?; true end - def quux=(v); 'quux=' end - end + assert_deprecated(/alias_method_chain/) do + FooClassWithBarMethod.class_eval do + def quux!; 'quux!' end + def quux?; true end + def quux=(v); 'quux=' end + end - assert !@instance.respond_to?(:quux_with_baz!) - assert !@instance.respond_to?(:quux_with_baz?) - assert !@instance.respond_to?(:quux_with_baz=) + assert !@instance.respond_to?(:quux_with_baz!) + assert !@instance.respond_to?(:quux_with_baz?) + assert !@instance.respond_to?(:quux_with_baz=) - FooClassWithBarMethod.class_eval { include BarMethodAliaser } - assert_respond_to @instance, :quux_with_baz! - assert_respond_to @instance, :quux_with_baz? - assert_respond_to @instance, :quux_with_baz= + FooClassWithBarMethod.class_eval { include BarMethodAliaser } + assert_respond_to @instance, :quux_with_baz! + assert_respond_to @instance, :quux_with_baz? + assert_respond_to @instance, :quux_with_baz= - FooClassWithBarMethod.alias_method_chain :quux!, :baz - assert_equal 'quux!_with_baz', @instance.quux! - assert_equal 'quux!', @instance.quux_without_baz! + FooClassWithBarMethod.alias_method_chain :quux!, :baz + assert_equal 'quux!_with_baz', @instance.quux! + assert_equal 'quux!', @instance.quux_without_baz! - FooClassWithBarMethod.alias_method_chain :quux?, :baz - assert_equal false, @instance.quux? - assert_equal true, @instance.quux_without_baz? + FooClassWithBarMethod.alias_method_chain :quux?, :baz + assert_equal false, @instance.quux? + assert_equal true, @instance.quux_without_baz? - FooClassWithBarMethod.alias_method_chain :quux=, :baz - assert_equal 'quux=_with_baz', @instance.send(:quux=, 1234) - assert_equal 'quux=', @instance.send(:quux_without_baz=, 1234) + FooClassWithBarMethod.alias_method_chain :quux=, :baz + assert_equal 'quux=_with_baz', @instance.send(:quux=, 1234) + assert_equal 'quux=', @instance.send(:quux_without_baz=, 1234) + end end def test_alias_method_chain_with_feature_punctuation - FooClassWithBarMethod.class_eval do - def quux; 'quux' end - def quux?; 'quux?' end - include BarMethodAliaser - alias_method_chain :quux, :baz! - end + assert_deprecated(/alias_method_chain/) do + FooClassWithBarMethod.class_eval do + def quux; 'quux' end + def quux?; 'quux?' end + include BarMethodAliaser + alias_method_chain :quux, :baz! + end - assert_nothing_raised do - assert_equal 'quux_with_baz', @instance.quux_with_baz! - end + assert_nothing_raised do + assert_equal 'quux_with_baz', @instance.quux_with_baz! + end - assert_raise(NameError) do - FooClassWithBarMethod.alias_method_chain :quux?, :baz! + assert_raise(NameError) do + FooClassWithBarMethod.alias_method_chain :quux?, :baz! + end end end def test_alias_method_chain_yields_target_and_punctuation - args = nil + assert_deprecated(/alias_method_chain/) do + args = nil - FooClassWithBarMethod.class_eval do - def quux?; end - include BarMethods + FooClassWithBarMethod.class_eval do + def quux?; end + include BarMethods - FooClassWithBarMethod.alias_method_chain :quux?, :baz do |target, punctuation| - args = [target, punctuation] + FooClassWithBarMethod.alias_method_chain :quux?, :baz do |target, punctuation| + args = [target, punctuation] + end end - end - assert_not_nil args - assert_equal 'quux', args[0] - assert_equal '?', args[1] + assert_not_nil args + assert_equal 'quux', args[0] + assert_equal '?', args[1] + end end def test_alias_method_chain_preserves_private_method_status - FooClassWithBarMethod.class_eval do - def duck; 'duck' end - include BarMethodAliaser - private :duck - alias_method_chain :duck, :orange - end + assert_deprecated(/alias_method_chain/) do + FooClassWithBarMethod.class_eval do + def duck; 'duck' end + include BarMethodAliaser + private :duck + alias_method_chain :duck, :orange + end - assert_raise NoMethodError do - @instance.duck - end + assert_raise NoMethodError do + @instance.duck + end - assert_equal 'duck_with_orange', @instance.instance_eval { duck } - assert FooClassWithBarMethod.private_method_defined?(:duck) + assert_equal 'duck_with_orange', @instance.instance_eval { duck } + assert FooClassWithBarMethod.private_method_defined?(:duck) + end end def test_alias_method_chain_preserves_protected_method_status - FooClassWithBarMethod.class_eval do - def duck; 'duck' end - include BarMethodAliaser - protected :duck - alias_method_chain :duck, :orange - end + assert_deprecated(/alias_method_chain/) do + FooClassWithBarMethod.class_eval do + def duck; 'duck' end + include BarMethodAliaser + protected :duck + alias_method_chain :duck, :orange + end - assert_raise NoMethodError do - @instance.duck - end + assert_raise NoMethodError do + @instance.duck + end - assert_equal 'duck_with_orange', @instance.instance_eval { duck } - assert FooClassWithBarMethod.protected_method_defined?(:duck) + assert_equal 'duck_with_orange', @instance.instance_eval { duck } + assert FooClassWithBarMethod.protected_method_defined?(:duck) + end end def test_alias_method_chain_preserves_public_method_status - FooClassWithBarMethod.class_eval do - def duck; 'duck' end - include BarMethodAliaser - public :duck - alias_method_chain :duck, :orange - end + assert_deprecated(/alias_method_chain/) do + FooClassWithBarMethod.class_eval do + def duck; 'duck' end + include BarMethodAliaser + public :duck + alias_method_chain :duck, :orange + end - assert_equal 'duck_with_orange', @instance.duck - assert FooClassWithBarMethod.public_method_defined?(:duck) + assert_equal 'duck_with_orange', @instance.duck + assert FooClassWithBarMethod.public_method_defined?(:duck) + end end def test_delegate_with_case diff --git a/activesupport/test/test_case_test.rb b/activesupport/test/test_case_test.rb index 151b623171..9e6d1a91d0 100644 --- a/activesupport/test/test_case_test.rb +++ b/activesupport/test/test_case_test.rb @@ -205,15 +205,4 @@ class TestOrderTest < ActiveSupport::TestCase assert_equal :random, self.class.test_order assert_equal :random, Class.new(ActiveSupport::TestCase).test_order end - - def test_i_suck_and_my_tests_are_order_dependent! - ActiveSupport::TestCase.test_order = :random - - klass = Class.new(ActiveSupport::TestCase) do - i_suck_and_my_tests_are_order_dependent! - end - - assert_equal :alpha, klass.test_order - assert_equal :random, ActiveSupport::TestCase.test_order - end end diff --git a/guides/source/action_view_overview.md b/guides/source/action_view_overview.md index 8f6676dc65..71f3f8882c 100644 --- a/guides/source/action_view_overview.md +++ b/guides/source/action_view_overview.md @@ -182,7 +182,7 @@ One way to use partials is to treat them as the equivalent of subroutines; a way <p>Here are a few of our fine products:</p> <% @products.each do |product| %> - <%= render partial: "product", locals: {product: product} %> + <%= render partial: "product", locals: { product: product } %> <% end %> <%= render "shared/footer" %> @@ -197,7 +197,7 @@ these are the only options you want to pass, you can skip using these options. For example, instead of: ```erb -<%= render partial: "product", locals: {product: @product} %> +<%= render partial: "product", locals: { product: @product } %> ``` You can also do: @@ -217,7 +217,7 @@ By default `ActionView::Partials::PartialRenderer` has its object in a local var within product we'll get `@product` in the local variable `product`, as if we had written: ```erb -<%= render partial: "product", locals: {product: @product} %> +<%= render partial: "product", locals: { product: @product } %> ``` With the `as` option we can specify a different name for the local variable. For example, if we wanted it to be `item` instead of `product` we would do: @@ -231,7 +231,7 @@ The `object` option can be used to directly specify which object is rendered int For example, instead of: ```erb -<%= render partial: "product", locals: {product: @item} %> +<%= render partial: "product", locals: { product: @item } %> ``` we would do: @@ -304,7 +304,7 @@ In the `show` template, we'll render the `_article` partial wrapped in the `box` **articles/show.html.erb** ```erb -<%= render partial: 'article', layout: 'box', locals: {article: @article} %> +<%= render partial: 'article', layout: 'box', locals: { article: @article } %> ``` The `box` layout simply wraps the `_article` partial in a `div`: @@ -344,7 +344,7 @@ You can also render a block of code within a partial layout instead of calling ` **articles/show.html.erb** ```html+erb -<% render(layout: 'box', locals: {article: @article}) do %> +<% render(layout: 'box', locals: { article: @article }) do %> <%= div_for(article) do %> <p><%= article.body %></p> <% end %> @@ -407,7 +407,7 @@ stylesheet_link_tag :monkey # => Returns a link tag that browsers and feed readers can use to auto-detect an RSS or Atom feed. ```ruby -auto_discovery_link_tag(:rss, "http://www.example.com/feed.rss", {title: "RSS Feed"}) # => +auto_discovery_link_tag(:rss, "http://www.example.com/feed.rss", { title: "RSS Feed" }) # => <link rel="alternate" type="application/rss+xml" title="RSS Feed" href="http://www.example.com/feed" /> ``` @@ -789,7 +789,7 @@ time_select("order", "submitted") Returns a `pre` tag that has object dumped by YAML. This creates a very readable way to inspect an object. ```ruby -my_hash = {'first' => 1, 'second' => 'two', 'third' => [1,2,3]} +my_hash = { 'first' => 1, 'second' => 'two', 'third' => [1,2,3] } debug(my_hash) ``` @@ -814,7 +814,7 @@ The core method of this helper, form_for, gives you the ability to create a form ```html+erb # Note: a @person variable will have been created in the controller (e.g. @person = Person.new) -<%= form_for @person, url: {action: "create"} do |f| %> +<%= form_for @person, url: { action: "create" } do |f| %> <%= f.text_field :first_name %> <%= f.text_field :last_name %> <%= submit_tag 'Create' %> @@ -834,7 +834,7 @@ The HTML generated for this would be: The params object created when this form is submitted would look like: ```ruby -{"action" => "create", "controller" => "people", "person" => {"first_name" => "William", "last_name" => "Smith"}} +{ "action" => "create", "controller" => "people", "person" => { "first_name" => "William", "last_name" => "Smith" } } ``` The params hash has a nested person value, which can therefore be accessed with params[:person] in the controller. @@ -855,7 +855,7 @@ check_box("article", "validated") Creates a scope around a specific model object like form_for, but doesn't create the form tags themselves. This makes fields_for suitable for specifying additional model objects in the same form: ```html+erb -<%= form_for @person, url: {action: "update"} do |person_form| %> +<%= form_for @person, url: { action: "update" } do |person_form| %> First name: <%= person_form.text_field :first_name %> Last name : <%= person_form.text_field :last_name %> @@ -990,7 +990,7 @@ end Sample usage (selecting the associated Author for an instance of Article, `@article`): ```ruby -collection_select(:article, :author_id, Author.all, :id, :name_with_initial, {prompt: true}) +collection_select(:article, :author_id, Author.all, :id, :name_with_initial, { prompt: true }) ``` If `@article.author_id` is 1, this would return: @@ -1162,7 +1162,7 @@ Create a select tag and a series of contained option tags for the provided objec Example: ```ruby -select("article", "person_id", Person.all.collect {|p| [ p.name, p.id ] }, {include_blank: true}) +select("article", "person_id", Person.all.collect { |p| [ p.name, p.id ] }, { include_blank: true }) ``` If `@article.person_id` is 1, this would become: @@ -1225,7 +1225,7 @@ Creates a field set for grouping HTML form elements. Creates a file upload field. ```html+erb -<%= form_tag({action:"post"}, multipart: true) do %> +<%= form_tag({ action: "post" }, multipart: true) do %> <label for="file">File to Upload</label> <%= file_field_tag "file" %> <%= submit_tag %> <% end %> diff --git a/guides/source/active_record_migrations.md b/guides/source/active_record_migrations.md index 0e6c8c4f4a..a2b7b7a818 100644 --- a/guides/source/active_record_migrations.md +++ b/guides/source/active_record_migrations.md @@ -357,7 +357,7 @@ will append `ENGINE=BLACKHOLE` to the SQL statement used to create the table ### Creating a Join Table -Migration method `create_join_table` creates a HABTM join table. A typical use +Migration method `create_join_table` creates an HABTM join table. A typical use would be: ```ruby @@ -425,7 +425,7 @@ change_column :products, :part_number, :text This changes the column `part_number` on products table to be a `:text` field. Besides `change_column`, the `change_column_null` and `change_column_default` -methods are used specifically to change the null and default values of a +methods are used specifically to change a not null constraint and default values of a column. ```ruby diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md index 66626f41d1..f3d8e05089 100644 --- a/guides/source/active_support_core_extensions.md +++ b/guides/source/active_support_core_extensions.md @@ -506,6 +506,8 @@ Extensions to `Module` ### `alias_method_chain` +**This method is deprecated in favour of using Module#prepend.** + Using plain Ruby you can wrap methods with other methods, that's called _alias chaining_. For example, let's say you'd like params to be strings in functional tests, as they are in real requests, but still want the convenience of assigning integers and other kind of values. To accomplish that you could wrap `ActionController::TestCase#process` this way in `test/test_helper.rb`: @@ -550,8 +552,6 @@ ActionController::TestCase.class_eval do end ``` -Rails uses `alias_method_chain` all over the code base. For example validations are added to `ActiveRecord::Base#save` by wrapping the method that way in a separate module specialized in validations. - NOTE: Defined in `active_support/core_ext/module/aliasing.rb`. ### Attributes diff --git a/guides/source/form_helpers.md b/guides/source/form_helpers.md index c21a2ba613..2b71b5e04e 100644 --- a/guides/source/form_helpers.md +++ b/guides/source/form_helpers.md @@ -282,7 +282,7 @@ The resulting HTML is: </form> ``` -The name passed to `form_for` controls the key used in `params` to access the form's values. Here the name is `article` and so all the inputs have names of the form `article[attribute_name]`. Accordingly, in the `create` action `params[:article]` will be a hash with keys `:title` and `:body`. You can read more about the significance of input names in the parameter_names section. +The name passed to `form_for` controls the key used in `params` to access the form's values. Here the name is `article` and so all the inputs have names of the form `article[attribute_name]`. Accordingly, in the `create` action `params[:article]` will be a hash with keys `:title` and `:body`. You can read more about the significance of input names in the [parameter_names section](#understanding-parameter-naming-conventions). The helper methods called on the form builder are identical to the model object helpers except that it is not necessary to specify which object is being edited since this is already managed by the form builder. |