
odd has_many assignment behaviour
Reported by Kieran Huggins | January 16th, 2008 @ 01:03 PM
The behaviour I'm seeing is that you have to assign the first child with an = before you can add more children with << in a has_many relationship.
Comments and changes to this ticket
-
Kieran Huggins January 16th, 2008 @ 01:03 PM
- Assigned user set to Sam Smoot
-
Kevin Bullock January 16th, 2008 @ 03:15 PM
I can verify this against 0.2.5 and trunk. It works properly if you do this:
article.revisions.create(:content => 'Foo!')
...but not if you do this (as in the pastie):
x.article.revisions.create(:content => 'Foo!')
-
Kieran Huggins January 28th, 2008 @ 04:35 PM
this is sort of frustrating to work around - and seems completely mysterious to me :-(
I'll take a look through the source to see if I can track down the cause, but I doubt I'll be able to.
Hope I can help!
-
Kieran Huggins January 29th, 2008 @ 10:25 PM
- Assigned user cleared.
-
asceth January 30th, 2008 @ 02:35 AM
I'm not getting this problem. I wrote a spec for it in the data_mapper trunk and it passed.
First modify spec/models/person.rb to include
has_many :children, :class => 'Person', :foreign_key => 'parent_id' belongs_to :person, :foreign_key => 'parent_id'
(I was writing other specs for a self-referential has_many)
Then the has_many_association_spec:
it "should allow children to be added with << from the get go" do parent = Person.create(:name => "Parent") parent.children << Person.create(:name => "Child") parent.children.size.should == 1 parent.save parent.reload! parent.children.size.should == 1 end
-
Kieran Huggins January 30th, 2008 @ 02:57 AM
asceth: your code works for me too. does the code in the pastie work for you?
-
asceth January 30th, 2008 @ 03:06 AM
Yes its working for me but I have no idea what the "x." stuff is in the "merb -i" part. I did the code in the pastie without merb using a sandbox script that loads data_mapper and defines the classes like you had them. Then in irb I did the code you had in "merb -i" without the "x." parts.
-
Kieran Huggins January 30th, 2008 @ 03:55 AM
The "x" seems to be the problem area, so I've re-pastied the example with the "x" explained:
Thanks!
-
asceth January 30th, 2008 @ 04:40 AM
I believe the problem lies in HasManyAssociation::Set#method_missing...
As per the pastie:
x.article
is actually returning an array since a has_one is still a has_many technically. Taking a look at the #method_missing method which will be called when
x.article.revisions
is used has itself check if the x.article set responds to the method (it doesn't) goes on to check if Article has any associations by the name of "revisions" (it does) and then stores the results of calling #revisions on every item in x.article (which in this case is just one 'has_one') into an array instead of a TypedSet.
I believe thats the key to the problem because the array passed back does not have #create so the NoMethodError is thrown like in your pastie and also the array itself is not really an association persay.
However everything would work if that part of method_missing would be bypassed on a 'has_one' and the 3rd check is done which is it checks if the first item in the 'has_many' (in this case the article since there is only one) responds (and it does since it has the revisions association) and calls it.
So:
x.article.first.revisions
works like you'd expect it to. And allows the rest of the pastie to work.
Maybe HasOneAssociation should be a sub-class of HasManyAssociation?
-
Kevin Bullock January 30th, 2008 @ 03:33 PM
Interesting. So my question is, why is has_one behaving like has_many (with the association method returning an array)? That seems very strange. Shouldn't it return the single associated object, unboxed?
-
asceth January 30th, 2008 @ 04:27 PM
The has_one macro assigns a HasManyAssociation as there is no HasOneAssocation. I'm willing to write a sub-class of HasManyAssociation or maybe just sub-class HasNAssocation like HasMany does for HasOne if thats the direction it should be taken.
This directly affects me as I have a couple has_one relationships I have to work with.
-
Kieran Huggins January 30th, 2008 @ 08:32 PM
If I instantiate the Article separately, it works as advertised.
If I then assign that article to a noun and save it, it won't update the ArticleRevision.article_id to Article.id ..... BUT: if I then add a revision using
x.article.first.revisions << ArticleRevision.create(...)
and then call save on "x", it updates all the revisions to the proper Article.id.
Maybe that's just part of the same issue, but i thought I should bring it up!
-
Dan Kubb (dkubb) April 15th, 2008 @ 03:27 AM
- Milestone cleared.
-
Sam Smoot May 21st, 2008 @ 01:20 AM
- State changed from new to invalid
OK, this was apparently not very clear. The previous distant-association syntax was a finder convenience only. As asceth mentioned, it doesn't return an actual association. So this ticket is invalid.
Please Sign in or create a free account to add a new ticket.
With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »