简体   繁体   中英

Change type identifier in polymorphic association

I'm trying to use Rails's polymorphic associations in a slightly odd way and I'm running into a problem.

The polymorphic table is Address

class Address < ActiveRecord::Base
  belongs_to :addressable, polymorphic: true
end

I have a uniqueness constraint on my database so that the same address address association can't be added twice.

I also have a Trip model which needs two addresses. One is the trip's origin and the other is it's destination.

class Trip < ActiveRecord::Base
  has_one :origin, as: :addressable, class_name: 'Address'
  has_one :destination, as: :addressable, class_name: 'Address'
end

The problem is that when Rails creates an address which is associated with a trip, it uses the class name (which is "Trip") to fill in the addressable_type column. That means that if I try to make a trip with an origin and destination, rails attempts to add two rows with the same addressable_type and addressable_id . This obviously fails at the uniqueness constraint.

I could remove the uniqueness constraint but then I would just end up with duplicated records which would confuse Rails because it wouldn't know which record was the origin and which was the destination.

What I would really like to do is specify the string to use for addressable_type :

class Trip < ActiveRecord::Base
  has_one :origin, as: :addressable, class_name: 'Address', type: 'Trip Origin'
  has_one :destination, as: :addressable, class_name: 'Address', type: 'Trip Destination'
end

Is that possible? Is there another solution or do I need to rethink my database schema?

I would have thought that address shouldn't belongs_to a trip, since one address might be the origin and/or destination of multiple trips. This is especially true if you have a uniqueness constraint. The foreign key should be stored in the trip:

class Address < ActiveRecord::Base
  has_many :trips_as_origin, class_name: "Trip", foreign_key: "origin_id"
  has_many :trips_as_destination, class_name: "Trip", foreign_key: "destination_id"
end

class Trip < ActiveRecord::Base
  belongs_to :origin, class_name: "Address"
  belongs_to :destination, class_name "Address"
end

You would need to create a migration that adds origin_id and destination_id to Trip .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM