2017-02-11 3 views
4

나는 User이며, Stringemail 속성을 가지고 있습니다. 내 응용 프로그램에서 이메일을 처리하고 있습니다 그러나, 내가 먼저 지금처럼 (비는-지속) Email 객체로 변환하는 것이 바람직 찾기 :ActiveRecord 쿼리에 사용할 객체를 문자열로 변환하려면 어떻게해야합니까?

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

Email#to_sEmail#to_str 모두로 정의된다 단순히 원래 문자열 (예 : [email protected])이므로 클라이언트가 Email 또는 String을 처리하는지 여부에 관계없이 일반적으로 클라이언트에게 투명합니다.

ActiveRecord와 속성을 할당 할 때이 완벽하게 작동합니다 :

> email = Email.new('[email protected]') 
> user.email = email 

액티브가 email 속성은 문자열이고 그에 따라 Email 객체를 변환 것을 알고있다. 분명히

> email = Email.new('[email protected]') 
> User.find_by email: email 
ActiveRecord::StatementInvalid: can't cast Email to string 

, 난 그냥

> User.find_by email: email.to_s 

를 호출 할 수 있습니다하지만이 캐스트가 자동으로 수행 할 수있는 방법이있다 : 데이터베이스를 쿼리 할 때 다소 puzzlingly,이 작업을 수행하지 않는 이유는 무엇입니까?

+0

? Rails 4.2 이상에서는 typecasting 동작을 제어하기 위해 ['attribute'] (http://apidock.com/rails/v4.2.7/ActiveRecord/Attributes/ClassMethods/attribute)를 사용할 수 있습니다. – Max

+0

@Max 그는 AR이 이미 데이터베이스에서 원하는 유형을 올바르게 추론하고 있기 때문에'attribute'에 대한 커스텀'Type'을 정의 할 필요가 있습니다. 그러나 디폴트'Type'는'Email'을 어떻게 처리해야하는지 모릅니다. 또 다른 옵션은'Email'이'String'으로부터 상속 받거나 ('String'에 case equality 연산자 메소드를 패치하는 것)입니다. – coreyward

+0

@coreyward 네, 저는 to_s를 호출 할 커스텀 타입을 생각하고있었습니다. 'ActiveModel'에서 우선하는 것보다 더 깔끔한 것 같았 습니다만, 커스텀 타입을 정의하는 것은'to_s'가 호출되도록하기 위해 과도 할 수도 있습니다. 이것은 OP의 일반적인 패턴인지 여부에 따라 달라질 수 있으며 추가 수업을 위해 노력해야 할 것입니다. – Max

답변

0

모델에서 getter 메서드를 재정의하여 캐스트하고 반환 할 수 있습니다.

4

This is the responsible object ActiveModel의 문자열에 개체를 캐스팅하는 경우. 거기에서 serialize 메서드를 살펴보십시오 : 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]') 
관련 문제