mdeering / attribute_normalizer

Adds the ability to normalize attributes cleanly with code blocks and predefined normalizers
MIT License
475 stars 53 forks source link

first_or_create fails in Rails 4.2 #68

Closed tjsingleton closed 9 years ago

tjsingleton commented 9 years ago

Given a model like

class Artist < ActiveRecord::Base
  normalize_attributes :name
end

And I'm in a fresh rails console When I call first_or_create

artist  = Artist.where(name: 'John Doe').first_or_create!

Then I get an error

NoMethodError: super: no superclass method `name=' for #<Artist:0x007fcf95ec56f0>

This seems to because ActiveRecord has not defined the attribute methods. The odd thing is from reading the ActiveRecord source, it seems like define_attribute_methods should be invoked.

>> Artist.ancestors.select{|n| n.public_instance_methods.include?(:name=) }
=> [Artist(...)]

>> Artist.define_attribute_methods; Artist.ancestors.select{|n| n.public_instance_methods.include?(:name=) }
=> [Artist(...), #<#<Class:0x007fc3ec7868f8>:0x007fc3ec786970>]

My current workaround is

module AttributeNormalizer
  module ClassMethods
    alias_method :old_normalize_attributes, :normalize_attributes

    def normalize_attributes(*attributes, &block)
      define_attribute_methods
      old_normalize_attributes(*attributes, &block)
    end
  end
end
dmeremyanin commented 9 years ago

first_or_create method silently deprecated and has some bad side effects. Using find_or_create_by instead is fixing this issue.

See also https://github.com/rails/rails/commit/0096f53b25e68c3fc79429253f816fff4a4ee596.

tjsingleton commented 9 years ago

@dimko Thanks!