# Has\_many \<\< method returns a class with the wrong base type

**URL:** <https://www.ruby-forum.com/t/has-many-method-returns-a-class-with-the-wrong-base-type/50087>\
**Category:** Rails\
**Created:** [December 12, 2005, 10:04pm UTC](https://www.ruby-forum.com/t/has-many-method-returns-a-class-with-the-wrong-base-type/50087 "2005-12-12T22:04:43Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![seanwarburton](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/2bfe46/32.png) [@seanwarburton](https://www.ruby-forum.com/u/seanwarburton)\
**Post date:** [December 12, 2005, 10:04pm UTC](https://www.ruby-forum.com/t/has-many-method-returns-a-class-with-the-wrong-base-type/50087/1 "2005-12-12T22:04:43Z")

</div>

I posted this originally on the comp.lang.ruby newsgroup, but I was told  
to  
bring it here.

I have a layered one to many relationship situation that is having some  
weird problems. I’ve been trying to look for a solution but I can’t  
seem to find it, or am not certain what keywords I should search on.  
Okay lets explain the environment. A Ruby on Rails app, simple CMS.  
Just some little tweaks. But versioning needs to be supported, and some  
articles require that the body can have multiple pages. Also the  
Articles can have multiple types, so they use a Single table  
inheritance scheme.  
So I have the following classes.  
class Article \< ActiveRecord::Base  
has\_many :versions

```
def new_version(properties = {})
    self.pinned_version += 1
    properties[:version] = self.pinned_version
    self.versions << Version.new(properties)
end

```

end

class News \< Article  
end

# there are other sub classes of articles but for brevity I only

display one for example.

class Version \< ActiveRecord::Base  
belongs\_to :article  
has\_many :article\_pages  
end

class ArticlePage \< ActiveRecord::Base  
belongs\_to :version  
end

Now in my controller, I have a method that works like this…

# Method to create a new Article. Create’s it with the initiated type

# and creates the first version of the Article.

def create  
@article = create\_typed\_article(params[:article])  
@version = @article.new\_version(params[:version])

```
params[:article_page].each do |page_name, page_data|
    page = ArticlePage.new()
    page.page_number = page_name.match(/\d+/)[0]
    page.body = page_data
    @version.article_pages << page
end

if @article.save
    flash[:notice] = 'Article was successfully created.'
    redirect_to :action => 'list'
else
    render :action => 'new'
end

```

end

Now the problem is, on the line “@version.article\_pages \<\< page”, I get  
the following error:  
undefined method `article\_pages’ for Version:Class

But if I open up the console, and do the following…  
v = Version.find(:conditions =\> [‘version = ? AND article\_id = ?’, 1,  
1])  
v.article\_pages

It works just fine. Now looking more closely at the error, it appears  
that the Version object that is returned by new\_version inherits from  
Class instead of ActiveRecord::Base. Therefore it doesn’t seem to have  
the collection of ArticlePage objects.

Well, it seems that the problem is that the @version.article\_pages \<\<  
method  
returns an object with the wrong base type. Other methods from the  
collection such as find and the index return an object with the right  
base  
type.

I guess I can change my method to this:  
def new\_version(properties = {})  
self.pinned\_version += 1  
properties[:version] = self.pinned\_version  
version = Version.new(properties)  
self.versions \<\< version  
version  
end  
But that just seems to circumvent some of the niceities of the Ruby  
language, and might as well be programming in Java or C#.  
Anyone else run into this problem? Is there a solution? Is this a bug,  
or by some sort of wicked design?

Thanks,

–  
Sean W.  
master nerd of  
i heart squares, Co.

3711 N. Ravenswood Ave. #147 Chicago, IL 60613  
Ph. (773) 531-6301 Fx. (773) 529-7041  
[http://www.iheartsquares.com](http://www.iheartsquares.com)

---

<div class="post-metadata">

**Author:** ![seanwarburton](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/2bfe46/32.png) [@seanwarburton](https://www.ruby-forum.com/u/seanwarburton)\
**Post date:** [December 12, 2005, 11:07pm UTC](https://www.ruby-forum.com/t/has-many-method-returns-a-class-with-the-wrong-base-type/50087/2 "2005-12-12T23:07:33Z")

</div>

Sean W. wrote:

> I posted this originally on the comp.lang.ruby newsgroup, but I was told  
> to  
> bring it here.
> 
> I have a layered one to many relationship situation that is having some  
> weird problems. I’ve been trying to look for a solution but I can’t  
> seem to find it, or am not certain what keywords I should search on.  
> Okay lets explain the environment. A Ruby on Rails app, simple CMS.
> 
> Now in my controller, I have a method that works like this…
> 
> Now the problem is, on the line “@version.article\_pages \<\< page”, I get  
> the following error:  
> undefined method `article\_pages’ for Version:Class
> 
> But if I open up the console, and do the following…  
> v = Version.find(:conditions =\> [‘version = ? AND article\_id = ?’, 1,  
> 1])  
> v.article\_pages
> 
> It works just fine. Now looking more closely at the error, it appears  
> that the Version object that is returned by new\_version inherits from  
> Class instead of ActiveRecord::Base. Therefore it doesn’t seem to have  
> the collection of ArticlePage objects.
> 
> Well, it seems that the problem is that the @version.article\_pages \<\<  
> method  
> returns an object with the wrong base type. Other methods from the  
> collection such as find and the index return an object with the right  
> base  
> type.

The problem, by the way, seems to be that ‘Version:Class’ error,  
which indicates that the method called is Version.article\_pages,  
not Version.new.article\_pages as it should.

Some more framework knowledge is required for figuring out why  
this is the case.

> Thanks,  
> Sean W.

E (from ruby-talk)

---

<div class="post-metadata">

**Author:** ![seanwarburton](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/2bfe46/32.png) [@seanwarburton](https://www.ruby-forum.com/u/seanwarburton)\
**Post date:** [December 13, 2005, 12:05am UTC](https://www.ruby-forum.com/t/has-many-method-returns-a-class-with-the-wrong-base-type/50087/3 "2005-12-13T00:05:11Z")

</div>

On 12/12/05, Eero S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > 
> 
> The problem, by the way, seems to be that ‘Version:Class’ error,  
> which indicates that the method called is Version.article\_pages,  
> not Version.new.article\_pages as it should.
> 
> Some more framework knowledge is required for figuring out why  
> this is the case.

First off, why do you have to be so rude in your answer.

Secondly, your answer is wrong. Actually looking at the return value,  
it’s  
an Array.

Version.new() is called, and creates a new object of type Version.  
That object is then added by the Article.article\_pages \<\< method. This  
method adds the object to the array of Version objects, then it returns  
the  
actual Article.article\_pages objec with the new Version object added to  
it.

So actually the correct answer would be on the other end of the  
new\_version  
method I should then grab the last item in the array. Or I can simply  
change  
my new\_version method to:

def new\_version(properties = {})  
self.pinned\_version += 1  
properties[:version] = self.pinned\_version  
(self.versions \<\< Version.new(properties))[-1]  
end

I just didn’t notice the little “[” before the returned  
"#\<Version:0x3804048 … " when i first was investigating the problem.

It would have been easy to just remind me that my assumption that the \<\<  
method returns the object added instead of the actual object. But  
instead  
you deside to act like a know it all, and give me a wrong answer.  
Understand  
the problem first before making such rude responses publicly.

–  
Sean W.  
master nerd of  
i heart squares, Co.

3711 N. Ravenswood Ave. #147 Chicago, IL 60613  
Ph. (773) 531-6301 Fx. (773) 529-7041  
[http://www.iheartsquares.com](http://www.iheartsquares.com)

---

<div class="post-metadata">

**Author:** ![seanwarburton](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/2bfe46/32.png) [@seanwarburton](https://www.ruby-forum.com/u/seanwarburton)\
**Post date:** [December 13, 2005, 12:33am UTC](https://www.ruby-forum.com/t/has-many-method-returns-a-class-with-the-wrong-base-type/50087/4 "2005-12-13T00:33:27Z")

</div>

Sean W. wrote:

> On 12/12/05, Eero S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > > 
> > 
> > The problem, by the way, seems to be that ‘Version:Class’ error,  
> > which indicates that the method called is Version.article\_pages,  
> > not Version.new.article\_pages as it should.
> > 
> > Some more framework knowledge is required for figuring out why  
> > this is the case.
> 
> First off, why do you have to be so rude in your answer.

I am sorry if I came across that way; I was trying to explain  
what ruby was able to discern and why this might be the right  
place instead of ruby-talk.

> Secondly, your answer is wrong. Actually looking at the return value,  
> it’s  
> an Array.

“undefined method `article\_pages’ for Version:Class” refers to  
a situation like (you can test this in irb):

class Version  
end

Version.article\_pages

It is certainly possible that there are other issues, but  
this a strict interpretation of the error. I am not knowledgeable  
of any other issues, which is why this forum is probably better  
for further inquiries.

> Version.new() is called, and creates a new object of type Version.  
> That object is then added by the Article.article\_pages \<\< method. This  
> method adds the object to the array of Version objects, then it returns  
> the  
> actual Article.article\_pages objec with the new Version object added to  
> it.
> 
> So actually the correct answer would be on the other end of the  
> new\_version  
> method I should then grab the last item in the array. Or I can simply  
> change  
> my new\_version method to:
> 
> def new\_version(properties = {})  
> self.pinned\_version += 1  
> properties[:version] = self.pinned\_version  
> (self.versions \<\< Version.new(properties))[-1]  
> end
> 
> I just didn’t notice the little “[” before the returned  
> "#\<Version:0x3804048 … " when i first was investigating the problem.
> 
> It would have been easy to just remind me that my assumption that the \<\<  
> method returns the object added instead of the actual object. But  
> instead  
> you deside to act like a know it all, and give me a wrong answer.  
> Understand  
> the problem first before making such rude responses publicly.

Just attempting to help you based on the information  
you provided. Sorry again.

Is the problem solved or is this just a workaround?

> Sean W.

E

---

<div class="post-metadata">

**Author:** ![seanwarburton](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/2bfe46/32.png) [@seanwarburton](https://www.ruby-forum.com/u/seanwarburton)\
**Post date:** [December 13, 2005, 1:23am UTC](https://www.ruby-forum.com/t/has-many-method-returns-a-class-with-the-wrong-base-type/50087/5 "2005-12-13T01:23:36Z")

</div>

On 12/12/05, Eero S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > First off, why do you have to be so rude in your answer.
> 
> I am sorry if I came across that way; I was trying to explain  
> what ruby was able to discern and why this might be the right  
> place instead of ruby-talk.

Okay, sorry for gunning off there.

> Version.article\_pages  
> Right, but my problem was an assumption of how the \<\< method worked.  
> The following IRB clued me in:

> > a = Article.new  
> > =\> #\<Article:0x38130c0 @attributes={“sub\_category\_id”=\>nil,  
> > “last\_modified\_at”=\>  
> > nil, “type”=\>“RecordReview”, “approved”=\>0, “assignment\_id”=\>nil,  
> > “pinned\_versio  
> > n”=\>0, “author\_id”=\>nil, “published\_at”=\>nil, “read\_count”=\>0,  
> > “created\_at”=\>nil  
> > }, @new\_record=true\>  
> > a.versions  
> > =\> []  
> > v= a.new\_version  
> > =\> [#\<Version:0x3807ca8 @attributes={“rating”=\>nil, “artist”=\>nil,  
> > “bside\_artist  
> > “=\>nil, “store\_link”=\>nil, “abstract”=\>nil, “title”=\>””,  
> > “release\_year”=\>nil, “b  
> > est\_new\_music”=\>0, “record\_label”=\>nil, “version”=\>1, “genre”=\>nil,  
> > "bside\_title  
> > "=\>nil, “coverpic\_id”=\>nil, “article\_id”=\>0, “image\_id”=\>nil,  
> > “source”=\>nil}, @n  
> > ew\_record=true\>]  
> > v.class  
> > =\> Array

Now I could see that v was actually an array containing Version object.  
Didn’t see those little bracket thingies. After realizing that it was an  
Array, I was able to go back and re-read the Array \<\< method description  
in  
“Programming Ruby”. Despite my numerous reads before, I then realized  
that I  
had a misconception about that method, in which I thought it returned  
the  
added object, when in reality it returns the whole array with the added  
object.

I think I had the result confused with another method but I’m not quite  
sure  
which at the moment, since all i see as far as return values for most  
Array  
methods is the Array instance itself, or a new array instance.

> It is certainly possible that there are other issues, but  
> this a strict interpretation of the error. I am not knowledgeable  
> of any other issues, which is why this forum is probably better  
> for further inquiries.

Array does not have the article\_pages method. Which would give me the  
error  
i was having, except I do not understand why it said Version:Class when  
the  
error should be something like “undefined method `article\_pages’ for  
[]:Array”

Which in the following IRB is exactly what I get:

> > b = []  
> > =\> []  
> > b  
> > =\> []  
> > b.class  
> > =\> Array  
> > b.something  
> > NoMethodError: undefined method `something’ for []:Array  
> > from (irb):9

\> Just attempting to help you based on the information \> you provided. Sorry again. \> \> Is the problem solved or is this just a workaround?

Yes, sorry for the little heated exchange. You did help, but I just  
misunderstood your tone.

I was able to solve it by changing the new\_version method to act how I  
wished with as few lines as I was expecting

def new\_version(properties = {})  
self.pinned\_version += 1  
properties[:version] = self.pinned\_version  
(self.versions \<\< Version.new(properties))[-1]  
end

–  
Sean W.  
master nerd of  
i heart squares, Co.

3711 N. Ravenswood Ave. #147 Chicago, IL 60613  
Ph. (773) 531-6301 Fx. (773) 529-7041  
[http://www.iheartsquares.com](http://www.iheartsquares.com)
