Overriding AR accessors


#1

As I said in my previous post, I need to override some AR accessor
methods. I thought that alias_method would work, it didn’t, I believe
because AR methods are invoked via method_missing. I thought
alias_attribute would work, but apparently that just makes a copy of the
accessor methods, so the original and the alias both point to the same
thing.

What I got to work was this - I need to get the object’s name, unless
it’s nil and the object is a child in acts_as_tree.

def name
if read_attribute(:name)
read_attribute(:name)
elsif read_attribute(:parent_id)
self.parent.name
end
end

def real_name
read_attribute(:name)
end

I don’t know if I need the real_name accessor, but either way it’s ugly
to write out a method like the name method for each of the 10 attributes
I need to do this with. Any suggestions would be much appreciated.

Jason


#2

I’ve have to be overriding a lot of accessors to want to get any more
clever than:

def name
my_or_parental(:name)
end

def nationality
my_or_parental(:nationality)
end

def my_or_parental(attrib)
if read_attribute(attrib)
read_attribute(attrib)
elsif self.parent_id
self.parent.send(attrib)
end
end

Ciao,
Sheldon.


#3

Right on - I was thinking along those lines on the way home from work.
I’ve
never really done any programming of this type(is this
meta-programming?),
but I think I’m going to try for something like this:

defaults_to_parent :attr_1, :attr_2, :attr_3

I’ll post back if I get anything in case anyone else needs something
like
this.

Jason


#4

Hello Jason,

Right on - I was thinking along those lines on the way home from
work. I’ve never really done any programming of this type(is this
meta-programming?), but I think I’m going to try for something
like this:

defaults_to_parent :attr_1, :attr_2, :attr_3

I’ll post back if I get anything in case anyone else needs something
like this.

You can write something like this :

class MyModel < AR::B
def self.defaults_to_parent(*getters)
getters.each do |method|
class_eval(<<-EOM, FILE, LINE)
def #{method}
if read_attribute(:#{method})
read_attribute(:#{method})
elsif read_attribute(:parent_id)
self.parent.#{method}
end
end
EOM
end
end

defaults_to_parent :attr_1, :attr_2, :attr_3
end

(not tested)

HTH,

– Jean-François.


À la renverse.


#5

Thank you , Jean-François. As far as I can tell, it works perfectly. If
my object has a nil attribute, it defaults to the parent, and if the
paren’t attribute is nil too, it returns nil. I’m not sure if I
understand, though, what FILE and LINE do.

OK, those params are just for error reporting. I was thinking I would
have to use eval, I didn’t know about class_eval and it probably would
have taken me awhile to figure it out. Your help is much appreciated.

Jason