Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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
Jon Leighton jonleighton authored
3  activerecord/CHANGELOG
View
@@ -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:
39 activerecord/lib/active_record/associations/association.rb
View
@@ -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
6 activerecord/lib/active_record/reflection.rb
View
@@ -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
20 activerecord/test/cases/associations/has_many_associations_test.rb
View
@@ -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.