Наличие нескольких типов адресов и ассоциаций с моделью, используя полиморфный способ?

#ruby-on-rails

#ruby-on-rails

Вопрос:

Позвольте моделировать пользователя и событие.

Я хотел бы добавить адресную модель с этими вариантами использования:

  • Адрес имеет разные типы, например BillingAddress, DeliveryAddress и т.д. (должен ли я использовать наследование?)
  • У пользователя может быть несколько адресов разных типов. Например, у пользователя может быть 2 адреса выставления счетов и 3 адреса доставки.
  • Событие также может иметь несколько адресов разных типов.

Какой самый простой способ обрабатывать такие варианты использования в Rails? Или есть какой-нибудь gem для обработки этого?

Ответ №1:

Полиморфизм

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

 class Address < ApplicationRecord
  belongs_to :addressable, polymorphic: true
end

class User < ApplicationRecord
  has_many :addresses, as: :addressable
end

class Event < ApplicationRecord
  has_many :addresses, as: :addressable
end
  

Миграция данных

Вы можете просто сделать следующее

 $ rails g migration AddAddressableToAddresses addressable:references:polymorphic
  

Если вы хотите сделать это вручную, полиморфная ассоциация просто добавляет идентификатор, тип и индекс для обоих:

 def change 
  add_column :addresses, :addressable_id, :integer
  add_column :addresses, :addressable_type, :string
  add_index :addresses, [:addressable_id, :addressable_type]
end 
  

Наследование одной таблицы (STI)

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

Комментарии:

1. У вас есть пример миграции?

2. Что касается вашего ответа, как вы обрабатываете несколько типов адресов для пользователя? Нравится делать: class User < ApplicationRecord has_many :billing_addresses, as: :addressable has_many :shipping_addresses, as: :addressable end

3.С STI вы просто добавляете type:string атрибут к своей адресной модели, затем вы наследуете свои разные адреса из этой базовой адресной модели: class Address < ApplicationRecord class ShippingAddress < Address и так далее. Затем вы можете просто добавить has_many :shipping_addresses, as: addressable

4. В чем преимущества этого второго подхода?