2009-11-14 5 views
12

instance_eval 다음에 attr_accessor이 있고 그 뒤에 initialize이 있습니다. 계속``초기화 '': 정의되지 않은 메소드 'attr_accessor '`가 나타납니다. 왜이 기능이 작동하지 않습니까?초기화 할 때 attr_accessor를 사용할 수없는 이유는 무엇입니까?

이 코드는 다음과 같은 종류의 외모 : attr_accessor가 MyClass의 인스턴스 방법으로 정의되지 않기 때문에 당신은, 인스턴스에 attr_accessor 호출 할 수 없습니다

class MyClass 
    def initialize(*args) 
     instance_eval "attr_accessor :#{sym}" 
    end 
end 

답변

20

. 모듈 및 클래스에서만 사용할 수 있습니다.

class MyClass 
    def initialize(varname) 
    class <<self 
     self 
    end.class_eval do 
     attr_accessor varname 
    end 
    end 
end 

o1 = MyClass.new(:foo) 
o2 = MyClass.new(:bar) 
o1.foo = "foo" # works 
o2.bar = "bar" # works 
o2.foo = "baz" # does not work 
+0

class_eval을 varname의 값입니다 가정 : 당신은 그냥 작성해야 자기가 쓴 곳 – johannes

+4

아니에요. 'class << self; ...; 종료는 폐쇄가 아닙니다. 그 안에'varname'에 접근 할 수 없지만,'class_eval' 블록에서 액세스 할 수 있습니다. – sepp2k

+0

[반작용의 답] (http://stackoverflow.com/a/14978624/403664) 좋습니다. 확인 해봐. –

4

클리너 구현 (NB : 아래이 참조 클래스뿐 아니라 단일 인스턴스의 모든 인스턴스에 접근을 추가합니다 의견 난 당신과 같이 인스턴스의 메타 클래스에 attr_accessor 전화를 걸 의심) :

class MyClass 
    def initialize(varname) 
    self.class.send(:attr_accessor, varname) 
    end 
end 
+6

이것은 접근자를 'MyClass'의 인스턴스 메소드로 정의합니다. 그래서'o1 = MyClass.new (: foo)'와'o2 = MyClass.new (: bar)'를 가지고 있다면'o1'과'o2'는 모두'foo'와'bar'에 접근자를 가지고 있습니다. 의도 한 행동. – sepp2k

+0

맞아! 여기 내 선원이있어. 나는이 질문에 대답할만한 사람이 있으면 여기에 남겨 두겠다. –

+0

Rob의 솔루션은 훨씬 깨끗해 보입니다. 하지만 나는 하나의 인스턴스에 대해서만 접근자를 갖는 sepp2k의 솔루션을 고수 할 것입니다. – JAkk

4

롭 디부 아 피체는 거의 권리가 있습니다. 퍼팅과 동일

self.singleton_class.send(:attr_accessor, varname) 

또는

self.singleton_class.class_eval "attr_accessor :#{varname}" 

또는 내가 좋아하는 변형

self.singleton_class.class_exec do attr_accessor varname end 

을 상징에게

관련 문제