2010-11-27 4 views
7

그냥 궁금해서 어떤 차이가 레일 보석이 두 사이에 : 나는 write_inheritable_attribute에 좋은 문서를 찾을 수 없습니다, 그냥 몇 가지 보석을 읽고 있었다 레일의 기본 할당 대 상속 특성을 쓰기

write_inheritable_attribute(:sample, "sample") 
self.sample = "sample" 

근원은 이전 몇 번 사용했다 찾아 냈다. 감사!

답변

5

단순한 클래스 나 모듈의 경우에는 차이가 없지만 다른 모듈을 여러 개로드 할 수있는 복잡한 모듈의 경우 write_inheritable_attribute과 같은 메서드를 사용하면 범위를 걱정하지 않고도 쉽고 안정적으로 객체를 수정할 수 있습니다. , 개인/보호 된 방법 및 모든 종류의 간섭으로부터 루비 metaprogramming 마법 같은 method_missing.

즉, foo.sample = "sample"이라고 쓰면 속성을 설정하기 전, 후에 또는 대신 설정할 수있는 모든 종류의 작업이 있습니다. 특히 개체가 ActiveModel 또는 ORM을 사용하는 경우에 발생합니다. foo.write_inheritable_attribute(:sample, "sample")을 사용할 때 발생하는 일을 훨씬 효과적으로 제어 할 수 있습니다. 인스턴스 변수를 상속하지 않습니다

+1

감사를 생성합니다

class Counter class_attribute :count self.count = 0 def self.increment puts "==> #{self} increment" self.count += 1 end end class DogCounter < Counter end puts "Counter.count: #{Counter.count}" puts "DogCounter.count: #{DogCounter.count} -> nice, DogCounter inherits count from Counter" DogCounter.increment puts "DogCounter.count: #{DogCounter.count} -> as expected" puts "Counter.count: #{Counter.count} -> nice, it doesn't change count for Counter" Counter.increment puts "Counter.count: #{Counter.count}" puts "DogCounter.count: #{DogCounter.count} -> now each subclass can have their own class attribute that inherits default value from the superclass" 

. 아직 완전히 이해하고 있는지 모르지만 답을 고맙게 생각합니다. –

+2

많은 문맥을 얻지 않으면 루비의 고급 기능 중 일부를 설명하기가 어렵습니다. 나는 이런 종류의 기능들에 대해 아주 접근하기 쉬운 설명을 위해 "Metaprogramming Ruby"라는 책을 강력히 추천한다 : http://pragprog.com/titles/ppmetr/metaprogramming-ruby – bowsersenior

+0

고마워. 내 책장에 내 눈을 기다리고 있습니다. 아마 이번 주말에 균열을 줄거야. –

13

서브 클래스 :

>> class B ; end 
>> B.write_inheritable_attribute(:candy, 7) # => 7 
>> class C < B ; end 
>> C.read_inheritable_attribute(:candy)  # => 7 
2

상속 속성이 루비 클래스 변수에서 공유하는 문제를 해결하기 위해 주로 구현되었습니다 : 레일에서

>> class B ; @candy = 1 ; end 
>> B.instance_variable_get :@candy   # => 1 
>> class C < B ; end 
>> C.instance_variable_get :@candy   # => nil 

는 상속 속성은 솔루션을 제공 클래스 상속. 레일 이후 3.2 write_inheritable_attribute 제거되었음을이이 출력을

Counter.count: 0 
DogCounter.count: 0 -> nice, DogCounter inherits @@count from Counter 
==> DogCounter increment 
DogCounter.count: 1 -> as expected 
Counter.count: 1 -> but Counter.count is also changed! 
==> Counter increment 
Counter.count: 2 
DogCounter.count: 2 -> @@count is shared with all the descendants of Counter 

참고 생산할 예정이 예를

class Counter 
    @@count = 0 
    def self.count 
    @@count 
    end 

    def self.increment 
    puts "==> #{self} increment" 
    @@count += 1 
    end 
end 

class DogCounter < Counter 
end 

puts "Counter.count: #{Counter.count}" 
puts "DogCounter.count: #{DogCounter.count} -> nice, DogCounter inherits @@count from Counter" 

DogCounter.increment 
puts "DogCounter.count: #{DogCounter.count} -> as expected" 
puts "Counter.count: #{Counter.count} -> but Counter.count is also changed!" 

Counter.increment 
puts "Counter.count: #{Counter.count}" 
puts "DogCounter.count: #{DogCounter.count} -> @@count is shared with all the descendants of Counter" 

을 고려한다. 우리는이 같은 것을 구현할 수있는 클래스 속성 (상속 속성을 무엇을 사용했는지)와 http://dev.mensfeld.pl/2012/01/upgrading-to-rails-3-2-0-from-rails-3-1-3/

를 참조하십시오이이 출력을

Counter.count: 0 
DogCounter.count: 0 -> nice, DogCounter inherits count from Counter 
==> DogCounter increment 
DogCounter.count: 1 -> as expected 
Counter.count: 0 -> nice, it doesn't change count for Counter 
==> Counter increment 
Counter.count: 1 
DogCounter.count: 1 -> now each subclass can have their own class attribute that inherits default value from the superclass