【问题标题】:"has_many through" association doesn't work when using a custom ActiveRecord::Type (binary) column使用自定义 ActiveRecord::Type (binary) 列时,“has_many through”关联不起作用
【发布时间】:2019-03-31 23:19:57
【问题描述】:

我创建了以下 ActiveRecord 类型,虽然 has_many 关联运行良好,但 has_many :through 却不行:

# app/types/uuid_type.rb
class UuidType < ActiveRecord::Type::Binary
  def serialize(value)
    super(cast_to_uuid(value)&.raw)
  end

  def deserialize(value)
    cast_to_uuid(super(value)).to_s
  end

  def cast_value(value)
    cast_to_uuid(value).to_s
  end

  private

  def cast_to_uuid(value)
    return if value.nil?

    case value.size
    when 16 then UUIDTools::UUID.parse_raw(value) # From `uuidtools` gem
    when 36 then UUIDTools::UUID.parse(value)     # From `uuidtools` gem
    end
  end
end

# app/models/token.rb
class Token < ActiveRecord::Base
  attribute :id, UuidType.new, default: SecureRandom.uuid

  has_many :token_users
  has_many :users, through: :token_users
end

(我还写了一个完整的code to replicate the issue)。


has_many 生成的SQL where 子句与以下类似并且可以完美运行:

WHERE column = x'4e254953bcdb4793a485ac04131565a7'

虽然为has_many :through 生成的那个不起作用:

WHERE column = '4e254953-bcdb-4793-a485-ac04131565a7'

它不返回任何错误,而且不返回任何结果

问题是第二个 (has_many :through) 不包含 x 前缀,也没有删除连字符(如果我手动这样做,它可以解决问题)。

我能够使用 MySQLSQlite 以及 Rails 56 来复制该问题。

为什么has_many :through 关系不会为二进制类型生成相同的 SQL?以及如何让它发挥作用?

【问题讨论】:

  • 为什么你使用自定义AR类型创建uuid而不是使用mysql uuid类型列?
  • @MartinZinovsky 与 PostgreSQL 不同,我认为 MySQL 没有 uuid 类型 :) 无论如何,我现在无法更改它,因为该表已经有很多记录并且改变它会破坏其他东西。谢谢。
  • 谢谢,@MartinZinovsky!您发送的链接的示例中使用的列类型是binary。这就是我已经在使用的 :) 但是 Rails 还没有开箱即用地序列化/反序列化它,对吧?

标签: ruby-on-rails ruby activerecord


【解决方案1】:

事实证明这是一个 Rails 错误。

我已经在官方 repo 上提交了an issue,他们已经修复了它:

?https://github.com/rails/rails/pull/36847

【讨论】:

    【解决方案2】:

    我不确定它是否会有所帮助,但请转到 config/initializers/type.rb 并添加

    ActiveRecord::Type.register(:token_users, UuidType)
    

    【讨论】:

    • 基于ActiveRecord::Type.register docs 第一个参数应该是type_name 但是你这里有表名
    • 我不认为这是问题所在,否则has_many(没有:through)将不起作用。
    • 我刚刚测试过,确实不行。无论如何,谢谢。
    猜你喜欢
    • 2018-09-02
    • 2020-05-31
    • 1970-01-01
    • 2010-12-13
    • 1970-01-01
    • 2015-12-17
    • 2011-09-28
    • 2016-03-26
    • 2015-07-03
    相关资源
    最近更新 更多