Rails: Address model being used twice, should it be separated into two tables? -


i making ecommerce site, , have purchases 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

Popular posts from this blog

commonjs - How to write a typescript definition file for a node module that exports a function? -

openid - Okta: Failed to get authorization code through API call -

ios - Change Storyboard View using Seague -