Как заставить ассоциации работать в построенных и несохраненных объектах?

Скажем, у меня есть что-то вроде:

@order = Order.new(status: :pending)

@item  = @order.items.build(title: "Shirt")

Когда я пытаюсь позвонить @item.order, я получаю сообщение об ошибке не найден, я думаю, потому что он все еще не сохранен для БД, но как он может указывать на построенный объект без сохранения каких-либо объектов?

@item.order # Not Found - Tries to fetch from the DB

Ответ 1

Чтобы выполнить эту работу, вы должны сообщить ассоциации order модели вашего объекта, что она является обратной вашей ассоциации items или вы заказываете модель и наоборот:

Вот так:

class Item < ActiveRecord::Base
  belongs_to :order, inverse_of: :items
end

class Order < ActiveRecord::Base
  has_many :items, inverse_of: :order
end

Таким образом, ваши ассоциации будут настроены правильно даже до сохранения в базе данных.

РЕДАКТИРОВАТЬ: Если вы этого не хотите, вы всегда можете назначить ассоциацию явно:

@item = @order.items.build(title: "Shirt")
@item.order = @order

или в одной строке:

@item = @order.items.build(title: "Shirt", order: @order)

Ответ 2

Я тестировал это в Rails 4.0.1, и похоже, что использование inverse_of больше не требуется, поскольку ассоциации выведены правильно. Он был рассмотрен в этой фиксации: https://github.com/rails/rails/pull/9522

Стоит отметить, что до сих пор нет решения для отношений has_many through:.

Ответ 3

То, что у @order еще нет идентификатора. Поэтому при вызове @order.items.build элемент имеет поле nil в order_id и, следовательно, не может найти нужный вам порядок.

Я предлагаю вам использовать вложенные атрибуты, чтобы сохранить некоторые связанные записи вместе.