问题
I want to override/extend a Rails has_one
association method so that it always returns an instance of the associated class. (If none already exists in the database, I want to create a new one and assign it to the parent instance.)
Ideally, I'd like to do this through the built-in Rails association extension mechanism. However, I don't know the name of the "getter" method, and so I don't know what to override.
How do I override the association getter so that I can instantiate a new object when it's nil?
回答1:
As of Rails 3, alias_method is not the preferred way to override association methods. Quoting from the docs:
Overriding generated methods
Association methods are generated in a module that is included into the model class, which allows you to easily override with your own methods and call the original generated method with super. For example:
class Car < ActiveRecord::Base belongs_to :owner belongs_to :old_owner def owner=(new_owner) self.old_owner = self.owner super end end
If your model class is Project, the module is named Project::GeneratedFeatureMethods. The GeneratedFeatureMethods module is included in the model class immediately after the (anonymous) generated attributes methods module, meaning an association will override the methods for an attribute with the same name.
回答2:
You can alias the original method, then define a new one with the same name.
For example:
class MyModel < ActiveRecord::Base
has_one :associated_model
alias :old_associated_model :associated_model
def associated_model
old_associated_model || AssociatedModel.new(my_model_id: id)
end
end
I don't know if this is the canonical way to handle this situation, but it should work.
来源:https://stackoverflow.com/questions/13055000/how-do-you-override-the-getter-method-for-a-rails-has-one-association