如何将对象转换为字符串以便与 ActiveRecord 查询一起使用?

2024-02-21

我有一个User,其中有一个String email属性。但是,当我在应用程序中处理电子邮件时,我发现最好先将其转换为(非持久)Email对象,就像这样:

class User < ActiveRecord::Base
  def email
    Email.new(self.read_attribute :email)
  end
end

Email#to_s and Email#to_str都被定义为简单的原始字符串(例如,[email protected] /cdn-cgi/l/email-protection),所以对于客户来说,他们是否正在处理一个通常是相当透明的Email or a String.

当分配属性时,这非常有效ActiveRecord:

> email = Email.new('[email protected] /cdn-cgi/l/email-protection')
> user.email = email

ActiveRecord 知道email属性是一个字符串并转换Email相应地反对。有点令人费解的是,它在查询数据库时并没有这样做:

> email = Email.new('[email protected] /cdn-cgi/l/email-protection')
> User.find_by email: email
ActiveRecord::StatementInvalid: can't cast Email to string

显然,我可以打电话

> User.find_by email: email.to_s

但是有没有办法让这个转换自动发生呢?


这是负责的对象 https://github.com/rails/rails/blob/92703a9ea5d8b96f30e0b706b801c9185ef14f0e/activemodel/lib/active_model/type/immutable_string.rb用于将对象转换为 ActiveModel 中的字符串。看看连载 https://github.com/rails/rails/blob/92703a9ea5d8b96f30e0b706b801c9185ef14f0e/activemodel/lib/active_model/type/immutable_string.rb#L8-L15那里的方法:它没有处理的情况Email.

您可以通过扩展类来添加一个:

module EmailSupport
  def serialize(value)
    case value
    when Email then value.to_s
    else super
    end
  end
end

ActiveModel::Type::ImmutableString.include(EmailSupport)

User.find_by email: Email.new('[email protected] /cdn-cgi/l/email-protection')
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将对象转换为字符串以便与 ActiveRecord 查询一起使用? 的相关文章

随机推荐