So I know how to override the default getters for attributes of an ActiveRecord object using
def custom_getter
return self[:custom_getter] || some_default_value
end
I'm trying to achieve the same thing however for a belongs to association. For instance.
class Foo < AR
belongs_to :bar
def bar
return self[:bar] || Bar.last
end
end
class Bar < AR
has_one :foo
end
When I say:
f = Foo.last
I'd like to have the method f.bar
return the last Bar, rather than nil if that association doesn't exist yet.
This doesn't work however. The reason is that self[:bar] is always undefined. It's actually self[:bar_id].
I can do something naive like:
def bar
if self[:bar_id]
return Bar.find(self[:bar_id])
else
return Bar.last
end
end
However this will always make a db call, even if Bar has already been fetched, which is certainly not ideal.
Does anyone have an insight as to how I might have a relationship such that the belongs_to attribute is only loaded once and has a default value if not set.
Best Answer
alias_method is your friend here.
The way this works is that you alias the default "bar" method as "original bar" and then implement your own version of "bar". If the call to original_bar returns nil then you return the last Bar instance instead.