问题
I have a User, which has a String email attribute. However, when I'm dealing with an email in my app, I find it desirable to first convert it to a (non-persisted) Email object, like so:
class User < ActiveRecord::Base
def email
Email.new(self.read_attribute :email)
end
end
Email#to_s and Email#to_str are both defined to be simply the original string (e.g., foo@bar.com), so it's usually pretty transparent to the client whether they're dealing with an Email or a String.
This works perfectly when assigning attributes with ActiveRecord:
> email = Email.new('foo@bar.com')
> user.email = email
ActiveRecord knows that the email attribute is a string and converts the Email object accordingly. Somewhat puzzlingly, it doesn't do this when querying the database:
> email = Email.new('foo@bar.com')
> User.find_by email: email
ActiveRecord::StatementInvalid: can't cast Email to string
Obviously, I can just call
> User.find_by email: email.to_s
But is there a way to make this cast happen automatically?
回答1:
This is the responsible object for casting an object to a string in ActiveModel. Take a look at the serialize method there: it doesn't have a case for handling Email.
You can add one by extending the class:
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')
回答2:
You can override the getter method in your model to cast it and return the string.
来源:https://stackoverflow.com/questions/42182553/how-can-i-cast-an-object-to-string-for-use-with-activerecord-queries