Rails: Address model being used twice, should it be separated into two tables? -
i making ecommerce site, , have purchase
s has_one :shipping_address
, has_one :billing_address
in past way i've implemented structure models so:
class address < activerecord::base belongs_to :billed_purchase, class_name: purchase, foreign_key: "billed_purchase_id" belongs_to :shipped_purchase, class_name: purchase, foreign_key: "shipped_purchase_id" belongs_to :state end class purchase < activerecord::base incomplete = 'incomplete' belongs_to :user has_one :shipping_address, class: address, foreign_key: "shipped_purchase_id" has_one :billing_address, class: address, foreign_key: "billed_purchase_id" ... end
as can see, reuse address
model , mask else using different foreign keys.
this works find, there cleaner way this? should using concerns? i'm sure behavior of these 2 models 100% same, i'm not sure if splitting them 2 tables way go. tips.
edit original version of wrong. have corrected , added note bottom.
you shouldn't split 2 models unless have other compelling reason so. 1 thing might consider, though, making address model polymorphic. this:
first: remove specific foreign keys addresses , add polymorphic type , id columns in migration:
remove_column :addresses, :shipping_purchase_id remove_column :addresses, :billing_purchase_id add_column :addresses, :addressable_type, :string add_column :addresses, :addressable_id, :integer add_column :addresses, :address_type, :string add_index :addresses, [:addressable_type, :addressable_id] add_index :addresses, :address_type
second: remove associations address
model , add polymorphic association instead:
class address < activerecord::base belongs_to :addressable, polymorphic: true ... end
third: define associations purchase
model:
class purchase < activerecord::base has_one :billing_address, -> { where(address_type: "billing") }, as: :addressable, class_name: "address" has_one :shipping_address, -> { where(address_type: "shipping") }, as: :addressable, class_name: "address" end
now can work them this:
p = purchase.new p.build_billing_address(city: "phoenix", state: "az") p.build_shipping_address(city: "indianapolis", state: "in") p.save! ... p = purchase.where(...) p.billing_address p.shipping_address
in controllers , views work have except access purchase
address
calling address.addressable
instead of address.billed_purchase
or address.shipped_purchase
.
you can add additional address joins purchase
or other model defining association :as
option, flexible without model changes.
there disadvantages polymorphic associations. importantly, can't eager fetch address side in above setup:
address.where(...).includes(:addressable) # <= fail error
but can still purchase side, you'd need anyway.
you can read on polymorphic associations here: active record association guide.
edit note: in original version of this, neglected add address_type
discriminator column. pernicious because seem working, you'd wrong address records after fact. when use polymorphic associations, , want associate model model in more 1 way, need third "discriminator" column keep track of 1 which. sorry mixup!
Comments
Post a Comment