23tux
23tux

Reputation: 14736

Multiple has_one relations to the same model

I have a User and a Shop model (Rails 5.2) that should have multiple locations like ship_location, bill_location... How can I use the same Location multiple times for this?

The User and Shop model could look something like this

class User
  has_one :ship_location
  has_one :bill_location
end

class Shop
  has_one :ship_location
  has_one :bill_location
  has_one :contact_location
end

But I can't figure out how the Location model should look like. It should be as abstract as possible, so that I don't have to define a new relationship and/or models when the Location is used for another model.

I guess I have to use some sort of polymorphism:

class Location
  # location has owner_id and owner_type
  belongs_to :owner, polymorphic: true
end

But this doesn't work, because user.ship_location is ambiguous (it would look for owner_type == "User" and owner_id == 1 but because there is also a bill_location with the same owner_type and owner_id, it doesn't work).

Do I need to create separate models for this, that share the same table?

Upvotes: 0

Views: 309

Answers (1)

Anand
Anand

Reputation: 6531

1 => Take a column (let's say location_type Or any column which can make difference between shipping location,billing location, and contact location) in Location model

class User
  has_one :ship_location, -> { where("location_type = ?", 'ship') }, :class_name => "Location", :dependent => :destroy
  has_one :bill_location, -> { where("location_type = ?", 'bill') }, :class_name => "Location", :dependent => :destroy
end

class Shop
  has_one :ship_location, -> { where("location_type = ?", 'ship') }, :class_name => "Location", :dependent => :destroy
  has_one :bill_location, -> { where("location_type = ?", 'bill') }, :class_name => "Location", :dependent => :destroy
  has_one :contact_location, -> { where("location_type = ?", 'contact') }, :class_name => "Location", :dependent => :destroy
end

class Location
  belongs_to :user
  belongs_to :shop
  # (has column 'location_type')
end

2 => While creating Location provide it's respective value (i.e ship, bill, contact) example -> Let's say create location for shop for loation_type = bill

Location.create(location_type: 'ship', foo: 'bar' ...)

Upvotes: 1

Related Questions