views:

35

answers:

2

In Ruby on Rails, say a Story object can "has_many" Vote objects (a story is voted "hot" by many users).

So when we do a

s = Story.find(:first)

s is a Story object, and say

s.votes

returns [] and

s.votes.class

returns Array

So clearly, s.votes is an empty Array object.

At this time, when

s.votes.create

is called, it actually invokes a method of the Vote class? How come an Array class object can invoke a Vote class method?

+1  A: 

votes is not an array, it's a method of a Story object. If you call it alone, it returns an array of all Vote records associated with that Story. The reason you are given Array when you do s.votes.class is that s.votes is returning an array (which in this case is empty because s has no votes) and you're checking the class of the returned array.

In turn, s.votes.create is another method dynamically generated by Rails based on your model associations. It's not a method of Array.

Jimmy Cuadra
Ruby can have this model association capability? in other languages, i think even when s.votes is a method and when it returns an empty Array object, then s.votes.create is forced to be the same as [].create, i think
動靜能量
Ruby isn't magic enough to return one thing if you call a method 'bare', but then return something else if you're chaining more methods.
Gareth
+4  A: 

In your case, .votes is not returning an Array, it's returning a special Association object.

The reason it looks like an Array is because the association object delegates all of its methods except for the dynamic ones like create to an array object it holds internally. And, this means that when you call .class on the object, that also gets delegated to the Array object.

Gareth
That's a better explanation of what I was attempting to describe.
Jimmy Cuadra