I have an Business
model and an polymorphic Address
model.
Each business has one main address but I would like advise on if it is better to have business belong_to
the polymorphic model or if it is better to say each business has_one address
belongs_to :main_location_address, class_name: "Address"
has_one :main_location_address, class_name: "Address", as: :addressable
I have tried both but belongs_to still requires a addressable attribute for the address.
Also how would this work with accepts_nested_attributes_for
in the Business
model and in the controller?
CodePudding user response:
When representing relationships between entities it is important to reflect them in such a way that there is a logical resemblance to their real life counterparts.
It makes sense to say
Business has one address/main address
rather than saying Business belongs to an address.
If you want to enforce a database constrain that a business can only have one address, you can create a unique index. Since it is a polymorphic relation, I'm assuming it will be used by other models as well. If you do not need to enforce uniqueness for all models, you could go for a partial index to create a unique index only where addressable_type is Business.
class AddIndexToAddress < ActiveRecord::Migration
def change
add_index :addresses, [:addressable_id, :addressable_type], unique: true, where: "addressable_type = 'Business'"
end
end
This will work if you only need strictly one address per business.
It is not clear from the question if you have an additional relationship to manage multiple addresses for a business as well. In that case you need opt for a belong_to relationship with business containing the main address id.
class Business < ApplicationRecord
belongs_to :main_address, class_name: 'Address', foreign_key: :address_id, optional: true
has_many :addresses, class_name: 'Address', as: :addressable
end
You can add validations as per your business requirements.
CodePudding user response:
If you want to ensure that a buisness actually can only have one main address then you need to use a belongs_to
assocation and create a foreign key column.
class AddMainLocationAddressToBuisnesses < ActiveRecord::Migration[7.0]
def change
add_reference :buisnesses, :main_location_address,
null: true,
foreign_key: { to_table: :addresses }
end
end
belongs_to :main_location_address, class_name: "Address", optional: true
Since the foreign key is stored on a column in the buisnesses table it can only have a single possible value per buisness.
has_one :main_location_address, class_name: "Address", as: :addressable
Will just fetch the first joined row off the addresses table. While you could monkey around and add addresses.main_location
boolean column It provides no guarentee that there actually is just one main location address per addressable unless you for example write a custom constraint.
But then again if you're using a polymorphic assocation you have already tossed referential integrity out the window.