#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. В чем преимущества этого второго подхода?