Путаница в методе сборки в ActiveRecord - PullRequest
1 голос
/ 16 августа 2011
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 ]

2 голосов
/ 16 августа 2011

Каждое отношение отличается от всех остальных.То есть, когда вы build Книга, принадлежащая u.boxes.first, все Rails заключают, что Книга принадлежит этой Коробке;это ничего не говорит о пользователе.

В этой ситуации, когда (предположительно) книги всегда принадлежат человеку, которому принадлежит ящик, в котором они находятся, вам, вероятно, лучше всего иметь отношения 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 и save в одной операции с create)

2 голосов
/ 16 августа 2011

Это должно быть

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

Поскольку вы build, метод здесь вызывается для box. И build работает так:

parent.children.build
# The same as:
parent.children.new(:parent_id => parent.id)

Так что здесь нет ничего о бабушке и дедушке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...