Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add an extremely lulzy deprecation warning which tries to detect if A…

…ssociationReflection#build_association has been overridden, but ignores the block argument.
  • Loading branch information...
commit 92c68dabd535e5ec180ad20d4e0ae1926a059d7d 1 parent 65813a6
@jonleighton jonleighton authored
View
3  activerecord/CHANGELOG
@@ -10,6 +10,9 @@
This change is necessary to fix https://github.com/rails/rails/issues/1842.
+ A deprecation warning and workaround has been added to 3.1, but authors will need to update
+ their code for it to work correctly in 3.2.
+
[Jon Leighton]
* AR#pluralize_table_names can be used to singularize/pluralize table name of an individual model:
View
39 activerecord/lib/active_record/associations/association.rb
@@ -1,5 +1,6 @@
require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/object/inclusion'
+require 'active_support/deprecation'
module ActiveRecord
module Associations
@@ -226,12 +227,48 @@ def association_class
end
def build_record(attributes, options)
- reflection.build_association(attributes, options) do |record|
+ reflection.original_build_association_called = false
+
+ record = reflection.build_association(attributes, options) do |r|
+ r.assign_attributes(
+ create_scope.except(*r.changed),
+ :without_protection => true
+ )
+ end
+
+ if !reflection.original_build_association_called &&
+ (record.changed & create_scope.keys) != create_scope.keys
+ # We have detected that there is an overridden AssociationReflection#build_association
+ # method, but it looks like it has not passed through the block above. So try again and
+ # show a noisy deprecation warning.
+
record.assign_attributes(
create_scope.except(*record.changed),
:without_protection => true
)
+
+ method = reflection.method(:build_association)
+ if RUBY_VERSION >= '1.9.2'
+ source = method.source_location
+ debug_info = "It looks like the method is defined in #{source[0]} at line #{source[1]}."
+ else
+ debug_info = "This might help you find the method: #{method}. If you run this on Ruby 1.9.2 we can tell you exactly where the method is."
+ end
+
+ ActiveSupport::Deprecation.warn <<-WARN
+It looks like ActiveRecord::Reflection::AssociationReflection#build_association has been redefined, either by you or by a plugin or library that you are using. The signature of this method has changed.
+
+ Before: def build_association(*options)
+ After: def build_association(*options, &block)
+
+The block argument now needs to be passed through to ActiveRecord::Base#new when this method is overridden, or else your associations will not function correctly in Rails 3.2.
+
+#{debug_info}
+
+ WARN
end
+
+ record
end
end
end
View
6 activerecord/lib/active_record/reflection.rb
@@ -174,9 +174,15 @@ def initialize(macro, name, options, active_record)
@collection = macro.in?([:has_many, :has_and_belongs_to_many])
end
+ # This is a hack so that we can tell if build_association was overridden, in order to
+ # provide an appropriate deprecation if the overridden method ignored the &block. Please
+ # see Association#build_record for details.
+ attr_accessor :original_build_association_called # :nodoc
+
# Returns a new, unsaved instance of the associated class. +options+ will
# be passed to the class's constructor.
def build_association(*options, &block)
+ @original_build_association_called = true
klass.new(*options, &block)
end
View
20 activerecord/test/cases/associations/has_many_associations_test.rb
@@ -1579,4 +1579,24 @@ def test_association_attributes_are_available_to_after_initialize
assert_equal car.id, bulb.attributes_after_initialize['car_id']
end
+
+ def test_overriding_reflection_build_association_with_deprecated_method_signature
+ ActiveRecord::Reflection::AssociationReflection.class_eval do
+ alias_method :old_build_association, :build_association
+
+ def build_association(*options)
+ klass.new(*options)
+ end
+ end
+
+ car = Car.create(:name => 'honda')
+ bulb = assert_deprecated { car.bulbs.build }
+
+ assert_equal car, bulb.car
+ ensure
+ ActiveRecord::Reflection::AssociationReflection.class_eval do
+ alias_method :build_association, :old_build_association
+ undef_method :old_build_association
+ end
+ end
end
Please sign in to comment.
Something went wrong with that request. Please try again.