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

Sas*_*lla 4 ruby activerecord ruby-on-rails

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

class User < ActiveRecord::Base
  def email
    Email.new(self.read_attribute :email)
  end
end
Run Code Online (Sandbox Code Playgroud)

Email#to_sEmail#to_str都被定义为简单的原始字符串(例如,foo@bar.com),因此对于客户端来说,无论他们正在处理 anEmail还是 a ,通常都是相当透明的String

当使用以下方式分配属性时,这非常有效ActiveRecord

> email = Email.new('foo@bar.com')
> user.email = email
Run Code Online (Sandbox Code Playgroud)

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

> email = Email.new('foo@bar.com')
> User.find_by email: email
ActiveRecord::StatementInvalid: can't cast Email to string
Run Code Online (Sandbox Code Playgroud)

显然,我可以打电话

> User.find_by email: email.to_s
Run Code Online (Sandbox Code Playgroud)

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

cor*_*ard 5

这是负责将对象转换为 ActiveModel 中的字符串的对象。看一下那里的序列化方法:它没有处理 的情况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('foo@example.org')
Run Code Online (Sandbox Code Playgroud)