Overriding one-to-many accessors


#1

I have a Person that has_many Things. I have defined a things method in
Person so that I can do some special filtering.

However, elsewhere I am doing “person.things << Thing.new…” and this
is now broken. Which, of course makes sense, because my overriden things
method just returns a filtered array of Thing objects… an array which
has now lost any of the one-to-many magic that rails would provide in
the original things method.

Any thoughts on dealing with this? Seems like I need to know what
enhanced array is being returned by rails so I can do the same thing.

thanks,

b


#2

Well, honestly the best thing I can come up with is, can you rename the
Person.things function you are defining to do the filtering?
So, instead do something like this
def filtered_things
return self.things.collect {|x| }
end
and leave the original things function alone?
It seems to me that your design is probably a bit skewed from what you
want
if you ALWAYS want the Person.things value to be filtered somehow…
perhaps
you are incorrectly defining the association… realize that you can put
conditions and such on the definition of the association, so if you only
wanted things with a status of 1, you could do
has_many :things, :conditions => ‘status = 1’
If you can specify the conditions in this manner, then you could leave
the
things function to behave the way it normally does, filtering your
results
via the association, and leaving the things << thing functionality open.


#3

Hey, thanks for the answer… and that’s basically what I’ve done for
now.

What the “filtering” actually is is combining the children of the
current object with the children of the current object’s ancestors (yes,
it’s acts_as_tree). So, it’s more a “building up” than a filtering.

This combined view is also the most commonly needed case, so I had
wanted to redefine the accessor so we didn’t need to remember to use the
“get-me-everything” version almost everywhere.

In fact, the other case – of just wanting the children of the current
object without regard to its ancestors – has not really come up as a
necessity yet.

I’ll get by with the alternately named method for now, but at some point
I hope to come back to this… once I have a better understanding of the
rails magic.

b


#4

Well, how about method aliasing?

def things_with_ancestors
#your current implementation of things goes here
end
alias_method :things_original, :things
alias_method :things, :things_with_ancestors

Now you can do Person.things to get your normal stuff and
Person.things_original to get the original implementation of it (that
works
with << and all that).


#5

Hmm, that sounds promising… will try it today.

b