【发布时间】: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 前缀,也没有删除连字符(如果我手动这样做,它可以解决问题)。
我能够使用 MySQL 和 SQlite 以及 Rails 5 和 6 来复制该问题。
为什么has_many :through 关系不会为二进制类型生成相同的 SQL?以及如何让它发挥作用?
【问题讨论】:
-
为什么你使用自定义AR类型创建
uuid而不是使用mysqluuid类型列? -
@MartinZinovsky 与 PostgreSQL 不同,我认为 MySQL 没有
uuid类型 :) 无论如何,我现在无法更改它,因为该表已经有很多记录并且改变它会破坏其他东西。谢谢。 -
谢谢,@MartinZinovsky!您发送的链接的示例中使用的列类型是
binary。这就是我已经在使用的 :) 但是 Rails 还没有开箱即用地序列化/反序列化它,对吧?
标签: ruby-on-rails ruby activerecord