2011-04-10 10 views
3

다른 사용자에게 동일한 리소스를 제공 할 수있는 애플리케이션을 개발하려고하고 있으며 리소스가 사용자에 따라 다른 유효성 검사 동작을 수행 할 수 있습니다.Ruby에서 동적 유효성 검사 및 메타 프로그래밍

나는 이것을 쉽게 풀기 위해 메타 프로그래밍을 사용하려고 시도했으나 문제에 대한 핵심 지식이 누락 된 것 같습니다.

가 나는 모델과 같은

class Profile < ActiveRecord::Base 
    # validates_presence_of :string1 
end 

모델은 때로는 필요하고 때로는 속성이 아니라 '문자열 1'을가함으로써 examplified 할 수 있습니다. 나는 (이 단순화에 식별 할 수없는 이유) 각 사용자에 대한 하위 클래스를 만들 싶습니다 내가하고 싶으 모듈 만들었습니다

module ExtendProfile 
    def self.included(base) 
    base.extend(ClassMethods) 
    end 

    module ClassMethods 
    def configure_validation(required) 
     if required 
     class_eval("ActiveRecord::Base.validates_presence_of :string1") 
     end 
    end 
    end 
end 

의 유일한 목적은을 추가하는 방법을 추가하는 것입니다 주어진 인수에 근거한 조건부 유효성 검사.

사실 인 인수로 호출 할 때 유효성 검사를 추가하지만 정상적으로 수행하지는 않습니다. 그것은 내가 생각한 것처럼 하위 클래스를 분리하지 않는 것으로 보입니다.

그것은 다음 시험에 의해 설명 될 수있다 :

profile = Profile.new 
profile.save; profile.errors 
=> [] 

프로파일은 기본적으로 오류없이 저장할 수 있습니다.

Object::const_set('FirstExtendedProfile'.intern, Class::new(Profile) { include ExtendProfile }) 
FirstExtendedProfile.configure_validation(true) 
fep = FirstExtendedProfile.new; fep.save; fep.errors 
=> {:string1=>["skal udfyldes", "skal udfyldes"]} 

새로운 서브 클래스를 생성하고 configuring_validation를 호출 유효성 검사를 추가하지만 몇 가지 이유로 그것을 검증하는 동안 두 번 호출됩니다 ("스칼 udfyldes"- 덴마크어이며이 필요하다는 것을 의미한다).

Object::const_set('SecondExtendedProfile'.intern, Class::new(Profile) { include ExtendProfile }) 
sep = SecondExtendedProfile.new; sep.save; sep.errors 
=> {:string1=>["skal udfyldes"]} 

는 또 다른 자손이 생성되고 비록 configure_validation은 여전히 ​​string1 속성을 (하지만 지금은 한 번만)의 유효성을 확인 호출되지 않습니다.

가 왜 특정 프로필 자손에 유효성 검사를 추가 할 수 없습니다입니다 ... 또 다른 후손을 추가 및 configure_validation 한 번 더 검증을 추가 호출?

저는 Ruby 1.9.2와 Rails 3.06을 사용하고 있습니다. 이 동적 클래스 생성을 작동시키는 방법을 이해하고 싶습니다. "표준"사용자 정의 유효성 검사를 알고 있습니다.

+0

특정 아직하지만 유효성 검사기의 목록이'액티브 :: base'의 직계 후손이며,이 변수가 그 자손 사이에 공유하는 클래스의 클래스 변수에 보관되어 있기 때문에 수 있습니다. 그렇습니다. – HakonB

답변

1

을, 유효성 검사는 "루트"클래스의 변수, 즉 ActiveRecord :: Base를 직접 상속하는 클래스에 저장됩니다. 당신의 노력이 효과가 없다는 것을 확인하기 위해 꽤 많은 일이 뒤쳐져 있습니다.

내 생각에는 각 클래스에 일부 구성 데이터를 저장 한 다음 구성을 검사하고 발견 한 내용에 따라 유효성을 검사하는 단일 동적 유효성 검사를 작성하는 것이 좋습니다. 그러나 이것은 "표준"사용자 정의 유효성을 알고 있음을 의미합니다."

with_options :if => lambda { |obj| obj.class.validation_configuration[:string1]} do |t| 
    t.validates_presence_of :string1 
end 
+0

예, 사용자 지정 유효성 검사를 수행하는 방법을 알고 있지만 문제는 그 문제를 파악하는 것입니다. 그것이 얼마나 검증되어야하는지는 사실 꽤 복잡합니다. 그리고 저는 한번만하고 나서 모든 것이 정적으로 설정된 "템플릿"클래스를 만들고 싶습니다. – HakonB

2

이 문제를 해결 ...보다는 확장 메타 프로그래밍 또는 클래스하지-확장 사용하는 다른 방법 : 단일 테이블 상속 작업을 할 때 명확하게 이유

class Profile 

    with_options :if => lambda { |o| o.required? } do |on_required| 
    on_required.validates_presence_of :string1 
    end 

end 
+0

감사합니다. 그러나이 방법으로이 사용자 지정을 알고 있습니다. 메타 프로그래밍 문제에 대한 해결책을 찾고있었습니다. – HakonB

관련 문제