我创建了以下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)。
为where
生成的SQL has_many
子句类似于以下内容并且工作正常:
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?你怎么能让它发挥作用呢?
事实证明这是一个Rails错误。
我已经提交了issue on the official repo,他们正在努力。
我不确定它是否会有所帮助,但请转到config / initializers / type.rb并添加
ActiveRecord::Type.register(:token_users, UuidType)