关于ActiveRecord中构建方法的困惑

时间:2011-08-16 12:47:33

标签: ruby-on-rails activerecord

class User < ActiveRecord::Base
    has_many :boxes
    has_many :books
end

class Box < ActiveRecord::Base
    belong_to :user
    has_many :books
end

class Book < ActiveRecord::Base
    belongs_to :user
    belongs_to :box
end

因此,当我在控制台中运行时,它按预期工作,创建一个新框并将user_id附加到框中

>> u = User.first
>> u.boxes.build(:height => 3, :width => 1, :length => 4)
>> u.save

然后我进一步尝试这个。已设置box_id,但未设置书籍中的user_id。

>> u.boxes.first.books.build(:title => 'Reading is fun')
>> u.save

似乎我在这里错过了一个非常基本的概念。

2 个答案:

答案 0 :(得分:2)

那应该是

u.boxes.first.books.build(:title => 'Reading is fun', :user_id => u.id)

因为build方法是box所以buildparent.children.build # The same as: parent.children.new(:parent_id => parent.id) 就是这样的:

{{1}}

所以这里没有祖父母。

答案 1 :(得分:2)

每个关系都与其他关系不同。也就是说,当你build属于u.boxes.first的书时,所有Rails推断的是该书属于那个盒子;它没有说明用户。

在这种情况下,(大概)书籍总是由拥有Box的人所拥有,你可能最好与has_many :through关系:

class User < ActiveRecord::Base
    has_many :boxes
    has_many :books, :through => :boxes
end

class Box < ActiveRecord::Base
    belong_to :user
    has_many :books
end

class Book < ActiveRecord::Base        
    belongs_to: box
    delegate :user, :to => :box # since belongs_to doesn't take :through
                                # passes Book#user through to Book#box.user
end

如果情况并非如此(也许你正在帮助我移动?),请按照原样保留关联,但是您必须手动设置至少一个关系,例如:

b = u.boxes.first.books.build(:title => "foo")
b.user = u
b.save

# or...
u.boxes.first.create_book(:title => "foo", :user => u)

(其他几点。在您的第二个示例中,您应该保存本书,而不是用户;并且您可以在build的单个操作中同时执行savecreate