OOP Question

On Rails using associations you can have something like this:

Category.find(1).articles #=> Array of Article objects

So if that returns an array how is something like this possible?

Category.find(1).articles.find_by_author_id(1)

Instead of calling the method "find_by_author_id" from the Article class shouldn't Ruby have called it from the Array class?

Thanks in advance

toulax wrote:

On Rails using associations you can have something like this:

Category.find(1).articles #=> Array of Article objects

So if that returns an array how is something like this possible?

Category.find(1).articles.find_by_author_id(1)

Instead of calling the method "find_by_author_id" from the Article class shouldn't Ruby have called it from the Array class?

Ruby is better OO than OO.

articles is both an Array and a live link between a Category and the Article class. So the Article class can do a method_missing() to concoct a find_by_whatever_column, and the articles link bequeaths to it a filter restricting the results to the current Category.

Good luck finding stuff like this in all the OO books out there...

Philip,

Thanks, I figured about the method_missing part, but how does Ruby know when to use Array and when to use Article in this case. Better yet, how could I reproduce this behavior?

Thanks

toulax wrote:

Thanks, I figured about the method_missing part, but how does Ruby know when to use Array and when to use Article in this case.

They are both. The capacities of Array and Article are merged together.

Try this:

def what?(anObject, aint = self)   p anObject.class.name   puts (anObject.public_methods - aint.public_methods).sort end

Call what?cat.articles, and it will probably report that articles is an Array. Then call what?cat.articles, , and it might report a bunch of extra methods that articles added to the array.

Better yet, how could I reproduce this behavior?

Look up Ruby metaprogramming, including the chapter called IIRC "write code with code" in the book /Rails Recipes/.

Hi --

On Rails using associations you can have something like this:

Category.find(1).articles #=> Array of Article objects

So if that returns an array how is something like this possible?

Category.find(1).articles.find_by_author_id(1)

Instead of calling the method "find_by_author_id" from the Article class shouldn't Ruby have called it from the Array class?

You don't call methods from a class; you send messages to objects, and the object looks for the method in the classes and modules in its lookup path. That sounds like splitting hairs, but it's an important conceptual and technical difference.

You've got an object that reports its class as Array -- but in Ruby, the class of an object does not definitively tell you what the object can do. In this particular case, the object has a method_missing hook that intercepts the message "find_by_author_id" and does something useful with it.

So that articles collection is an Array, as indicated by its class, but the main thing is that it's an object to which you can send certain messages and get a result. It doesn't much matter what it says its class is, since class membership doesn't govern an object's behavior.

David

I see now that the method is really being called on the Array, but it still seems quite hard to grasp so I'll have to look further into metaprogramming.

Thanks everyone