2010-01-11 66 views
8

我有两个型号导轨 - build_association不工作了HAS_ONE和belongs_to的关系

class Subscription < ActiveRecord::Base 
    belongs_to :client 
end 

class Client < ActiveRecord::Base 
    has_one :subscription 
end 

,但是当我尝试创建例如从孩子父母sub.build_client外键未被设置,例如

>> 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> 

它的工作,如果我做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 

伊夫花了3个小摆弄,得到了无处可去快。 任何人都可以解释我做错了什么,要检查的东西等

回答

9

根据您的模型协会,SubscriptionClient的孩子。

如果你先创建一个订阅,然后创建一个客户,按您的第一个例子,Rails有没有因为你还没有创建客户端记录该点设置subscriptions表内的client_id外键值的方式,所以没有什么可以与订阅相关联。这就是为什么您必须先创建父记录(即客户端),然后使用build_subscription方法将其与子订阅记录相关联。

+0

谢谢约翰,我认为这是这种情况(我曾经咨询了导轨指南,但没有找到这个解释,所以想在这里确认在stackoverflow)。但是,如何与has_many属于关系,这可以做到。 – robodisco 2010-01-11 12:13:41

+0

我只是想,如果它不能做,为什么是那里的构建方法?如果foreign_id不能在这种关系中设置该方法的用途? – robodisco 2010-01-11 12:18:41

+1

这是一个很好的问题。 – 2010-01-11 12:41:53

1

在我的项目中我有很多类似的协会,但我常常禁止CLIENT_ID设置为空,所以没有父对象,我不能创建子对象。

尝试:

sub = Subscription.new 
sub.build_client 
sub.save 

它会创建并保存两个对象。

0

在其中一个注释中,您问为什么build_client方法在那里。当您保存在客户端,然后检查子的CLIENT_ID,它是零,而且如果你会叫

sub.save(validate: false) 

,然后检查了子的CLIENT_ID,它会存在。所以尽管它需要额外的保存,但它仍然为sub创建外键的魔力。

1

这似乎已在Rails 4.2.5或更早版本中得到修复。 (我不确定最早的修复版本是什么,我只测试过4.2.5)

当父母被保存时,插入父记录后,会自动执行更新以添加父母ID到子记录。

但是我还没有找到任何有关此行为,相关代码或自动化测试的文档,所以我不确定它是否有意修复并且应该依赖此行为。在这里的其他答案中坚持解决方案可能是最好的。

这也似乎是仍然破坏for_many在Rails 4.2.5。