views:

338

answers:

3

I have two models

class Subscription < ActiveRecord::Base
  belongs_to :client
end

class Client < ActiveRecord::Base
  has_one :subscription
end

but when I try to create a parent from the child e.g. sub.build_client the foreign key does not get set e.g.

>> sub = Subscription.new
=> #<Subscription id: nil, token: nil, user_id: nil, created_at: nil, updated_at: nil, cancelled: nil, active: nil, client_id: nil>
>> sub.save(false);
?> client = sub.build_client
=> #<Client id: nil, server_id: nil, ip: nil, created_at: nil, updated_at: nil>
>> client.save(false)
=> true
>> sub.client_id
=> nil
>> sub
=> #<Subscription id: 4, token: nil, user_id: nil, created_at: "2010-01-11 06:07:45", updated_at: "2010-01-11 06:07:45", cancelled: nil, active: nil, client_id: nil>

It does work if I do client.build_subscription

?> client = Client.new
=> #<Client id: nil, server_id: nil, ip: nil, created_at: nil, updated_at: nil>
>> client.save(false)
=> true
>> sub = client.build_subscription
=> #<Subscription id: nil, token: nil, user_id: nil, created_at: nil, updated_at: nil, cancelled: nil, active: nil, client_id: 4>
>> sub.save(false)
=> true
>> sub
=> #<Subscription id: 5, token: nil, user_id: nil, created_at: "2010-01-11 06:09:32", updated_at: "2010-01-11 06:09:32", cancelled: nil, active: nil, client_id: 4>
>> client
=> #<Client id: 4, server_id: nil, ip: nil, created_at: "2010-01-11 06:09:02", updated_at: "2010-01-11 06:09:02">
>> ^C

Ive spent 3 hours fiddling and got nowhere fast. Can anyone explain what I'm doing wrong, things to check etc

+2  A: 

According to your model associations, a Subscription is a child of a Client.

If you create a subscription first and then create a client as per your first example, Rails has no way of setting a client_id foreign key value within the subscriptions table because at that point you haven't created the client record, so there's nothing to associate with the subscription. That's why you have to create the parent record (i.e. a client) first and then associate it with a child subscription record using the build_subscription method.

John Topley
thanks john, i thought this was the case (i did consult the rails guide but couldnt find this explained so wanted to confirm here on stackoverflow). But how come with a has_many belongs to relationship this can be done.
adam
I just thought as well if it cant be done why is the build method there? If the foreign_id cant be set whats the use for that method in this relationship?
adam
That's a good question.
John Topley
do you mean the one in my first reply, second reply or both? I might ask this actually as a new question.
adam
The second reply.
John Topley
+2  A: 

it doesn't work both ways, a parent can build a child with the build_association method but not vice versa.

read up : http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_one

keikun17
+1  A: 

In my projects I have many similar associations, but I often forbid setting client_id to null, so I can't create child object without parent object.

Try:

sub = Subscription.new
sub.build_client
sub.save

It will create and save both objects.

klew