我有两个型号
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个小时摆弄,无处可去。 任何人都可以解释我做错了什么,要检查的事情等等。
答案 0 :(得分:9)
根据您的模特关联,Subscription
是Client
的孩子。
如果您先创建订阅然后根据第一个示例创建客户端,则Rails无法在client_id
表中设置subscriptions
外键值,因为此时您还没有' t创建了客户端记录,因此没有任何内容可以与订阅相关联。这就是为什么你必须首先创建父记录(即客户端),然后使用build_subscription
方法将其与子订阅记录相关联。
答案 1 :(得分:3)
它无法双向工作,父级可以使用build_association方法构建子级,但反之亦然。
阅读:http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_one
答案 2 :(得分:1)
在我的项目中,我有许多类似的关联,但我经常禁止将client_id设置为null,因此我无法在没有父对象的情况下创建子对象。
尝试:
sub = Subscription.new
sub.build_client
sub.save
它将创建并保存两个对象。
答案 3 :(得分:1)
这似乎已在Rails 4.2.5或更早版本中得到修复。 (我不确定修复程序的最早版本是什么。我只测试了4.2.5。)
保存父级后,插入父级记录后,会自动执行更新,将父级ID添加到子级记录中。
但是,我还没有找到有关此行为,相关代码或自动化测试的任何文档,因此我不确定是否故意修复此行为并且应该依赖此行为。最好在这里的其他答案中坚持使用解决方案。
在Rails 4.2.5中,似乎仍然打破了has_many 。
答案 4 :(得分:0)
在其中一条评论中,您会问为什么build_client方法存在。当您保存客户端然后检查sub上的client_id时,它是nil,但是如果您还要调用
sub.save(validate: false)
然后检查sub上的client_id,它会存在。因此,虽然它需要额外的保存,但仍然可以为sub设置外键。