设置多态关联,其中关联表具有不同的主键类型(UUID和整数)

时间:2018-03-06 09:55:48

标签: ruby-on-rails ruby activerecord ruby-on-rails-5

我有5个表,likeable都是user,而likes表记录了这个。

问题是5个表中的一个使用uuid而不是主键的整数。所以我不能有一个典型的likeable_id& likeable_type

是否可以设置处理不同主键类型的多态关联?

提前致谢

2 个答案:

答案 0 :(得分:0)

我没有你的表名,但这是一个连接表的例子

class CreateJoins < ActiveRecord::Migration
  def change
    create_table :joins do |t|
      t.belongs_to :uuid_id_model, type: :uuid # you specify the type
      t.belongs_to :integer_id_model # you don't need anything
      t.index %i[uuid_id_model integer_id_model], unique: true
      t.timestamps
    end
  end
end

换句话说,在列上指定它们的类型uuid

如果您需要更改联接表的列类型,可以这样做:

class ChangeColumnType < ActiveRecord::Migration
  def change
    change_column :some_join_table, :some_join_column, :uuid
  end
end

答案 1 :(得分:0)

我最终得到的解决方案是添加likeable_id_string来存储任何uuid主键。然后我覆盖getter和setter来执行以下操作:

# Overriding getters and setters to handle multiple primary key types on
  # this polymorphic association ( String and Integer )

  # Setters
  def likeable=(value)
    if !value.nil? && value.id.is_a?(String)
      self[:likeable_id] = nil
      self[:likeable_id_string] = value.id
      self[:likeable_type] = value.class.name
    else
      self[:likeable_id_string] = nil
      super(value)
    end
  end

  # in case likeable_type and likeable_id are updated seperately. I believe
  # this is done in FE (rather than passing an object to .likeable)
  def likeable_id=(value)
    if !value.nil? && value.is_a?(String)
      self[:likeable_id] = nil
      self[:likeable_id_string] = value
    else
      self[:likeable_id_string] = nil
      super(value)
    end
  end

  # Getters
  def likeable
    if self.likeable_id
      return super
    elsif !self.likeable_type.nil?
      return self.likeable_type.constantize.find(likeable_id_string)
    else
      return nil
    end
  end

一旦我覆盖了likeable=,你会认为不需要likeable_id= setter ..但似乎是这样。如果有人知道为什么我需要这两个,请告诉我,因为likeable委托给likeable_idlikeable_type

似乎合乎逻辑

我觉得这是一个宝石的用例。我可能很快就会做的事情。如果您希望将此视为宝石(或者如果您认为这是一个可怕的想法),请与我们联系。