Rails: как использовать ассоциацию own_to для ссылки в дополнение к ассоциации has_many?

После настройки: у пользователя может быть много адресов, но хотя бы один из них является основным адресом. Внешний ключ в пользовательской таблице должен использоваться как указатель на запись основного адреса.

class User < ActiveRecord::Base
  has_many :addresses
  belongs_to :main_address, :class_name => 'Address', :foreign_key => 'main_address_id'

  accepts_nested_attributes_for :main_address
end


class Address < ActiveRecord::Base
  belongs_to :user # used for has_many
end

Эта настройка работает только для чтения main_address. Но создание - это проблема, например, при использовании его в сложной форме с вложенными атрибутами (адресными полями) для создания.

Я получаю следующую ошибку: SQLite3::ConstraintException: addresses.user_id may not be NULL:

Проблема в том, что адрес создается через main_address.build, а адрес не получает внешний ключ user_id, потому что он создается через main_address.

Понятия не имею :( Как я могу использовать ассоциацию own_to для правильной ссылки на ассоциацию has_many?


person MMore    schedule 14.07.2011    source источник


Ответы (2)


Хотя я согласен с равнодушием, альтернативой является установление ассоциации в AddressUser), а затем использование before_save для обновления user_id, если это необходимо. Что-то вроде этого:

has_one :main_user, :class_name => 'User', :foreign_key => 'main_address_id'

before_save :update_user_id

def update_user_id
  if main_user.present?
    self.user_id = main_user.id
  end
end
person smathy    schedule 15.07.2011

Ваше моделирование «реального» мира кажется немного странным, и аналогично ассоциация, которую вы пытаетесь создать, сложна. Кажется, что пользователь принадлежит к MainAddress не больше, чем пользователь принадлежит своему PrimaryVehicle. Почему бы не использовать логическое значение в модели Address, например Address # primary? ?

person Luke W    schedule 14.07.2011
comment
Конечно, это было бы решением, но я видел этот подход в другом программном проекте и считаю, что это умнее, чем просто использовать логический атрибут. Так что я надеюсь, что у кого-нибудь есть идея ... - person MMore; 14.07.2011