2016-07-05 7 views
0

나는 같은 인터페이스를한다고 가정 :모듈은 슈퍼

class SomeModel 
    include MagicModule 

    attribute :some_method1 
    attribute :some_method2 

    def some_method1; super end 
end 

그리고 MagicModule 뭔가 같다 :

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

module ClassMethods 
    def attribute(attribute_name) 
    define_method(attribute_name) { attribute_name.to_s } 
    end 
end 
end 

가 어떻게 MagicModule 일을 할 것 같은 그 def some_method1; super end 위 작품? 나는 이런 식으로 뭔가를 시도했습니다


:

module MagicModule 
extend ActiveSupport::Concern 

included do 
    hidden_module = Module.new do 
     def hidden_module; method(__callee__).owner end 
    end 
    extend hidden_module 
end 

module ClassMethods 
    def attribute(attribute_name) 
    hidden_module.send(:define_method, attribute_name) { attribute_name.to_s } 
    end 
end 
end 

그러나 행운.

+0

'some_method1'은 클래스의 두 번째 선언에 의해 덮어 쓰여지고 있습니다. 모듈을 포함하여 모듈을 '수퍼 클래스'로 만들지 않으므로'super' 호출이 실패합니다. 당신이 할 수있는 것은'attribute : some_method1; alias_method : old_some_method1, : some_method1; def some_method1; old_some_method1; 끝 ' – engineersmnky

+0

예, 알고 있습니다. 가능하다면 ..... 할 수 있으면 깨끗한 API를 제공하고 싶습니다. – s12chung

+0

누군가 게시하지 않으면 내가 해결할 수있는 것을 보지만 'MagicModule'이 이상하게 보일 수 있습니다. – engineersmnky

답변

2

접근자를 포함하는 모듈을 만드는 아이디어가 좋습니다 (예 : 레일스가 자동으로 생성 한 접근자를 위해 무엇을하는지). 당신은 모듈을 포함하는 대신이

module MagicModule 
    def self.included(base) 
    base.send(:extend, ClassMethods) 
    end 

    module ClassMethods 
    def attribute(attribute_name) 
     unless @hidden_module 
     @hidden_module = Module.new 
     include @hidden_module 
     end 
     @hidden_module.send(:define_method, attribute_name) { attribute_name.to_s } 
    end 
    end 
end 

난 당신이 SomeModel를 서브 클래스 경우 당신은 여전히 ​​서브 클래스에 새로운 속성을 정의 할 수 있도록 모듈이 작성되는 곳 주위에 이동 한 확장 할 그러나.

+0

아니요, super는 괜찮습니다. –

+0

이 예에서는'attribute'가 클래스 메소드가 아니기 때문에 예제를 제공해주십시오. – engineersmnky

+0

와우, ActiveSupport :: Concern을 없애 버렸어 - 물론 클래스 메소드 모듈을 확장해야합니다. 감사합니다 –