One way of a few to do this is to have more than one polymorphic class with the same purpose that duck type the same, one for ids and one for strings. I'll demonstrate with this Commentable
concern.
# bigint id migration
create_table :comments do |t|
t.references :commentable, polymorphic: true, null: true
...
end
# string id migration
create_table :string_id_comments do |t|
t.references :commentable, type: :string, polymorphic: true, null: true
...
end
Define models for StringIdComments
and Comments
. They could share code through a concern or through extension. The Commentable
concern now needs to decide which to use:
module Commentable
extend ActiveSupport::Concern
included do
if columns_hash[primary_key].type == :integer
has_many :comments, as: :commentable, dependent: :destroy
else
has_many :comments, as: :commentable, class_name: 'StringIdComments', dependent: :destroy
end
end
end
If you wished to query through Comment
, this has the downside of having two tables which could be eliminated by using these as through tables to the actual comment. I haven't tested, but it might also be solved by having two keys in a single polymorphic class, a string and a bigint, and specifying the key in the has_
.