2010-11-27 13 views
7

Sólo por curiosidad, cuál es la diferencia entre estos dos en una joya Rieles:escribir los atributos Heredable frente asignación básica en Rails

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

no pude encontrar ninguna buena documentación sobre write_inheritable_attribute, y estaba leyendo a través de alguna joya fuente y encontró que el primero usó algunas veces. ¡Gracias!

Respuesta

5

Para una clase o módulo simple, no habría una diferencia, pero con módulos más complejos que pueden cargarse con muchos otros módulos, métodos como write_inheritable_attribute pueden ayudarlo a modificar objetos de manera fácil y confiable sin tener que preocuparse por el alcance , métodos privados/protegidos y todo tipo de interferencia de la magia de metaprogramación de ruby ​​como method_missing.

En resumen, cuando escribe foo.sample = "sample", hay todo tipo de cosas que pueden suceder antes, después o en lugar de establecer el atributo, especialmente si el objeto usa ActiveModel o un ORM. Cuando usa foo.write_inheritable_attribute(:sample, "sample"), tiene mucho más control sobre lo que sucede.

+1

Gracias. Todavía no estoy seguro de entenderlo completamente, pero aprecio la respuesta. –

+2

Es difícil explicar algunas de las características avanzadas de Ruby a menos que tenga mucho contexto. Recomiendo encarecidamente el libro "Metaprogramación Ruby" para una explicación amplia y accesible de este tipo de características: http://pragprog.com/titles/ppmetr/metaprogramming-ruby – bowsersenior

+0

Gracias. Está en mi estantería esperando mis ojos. Probablemente lo rompa este fin de semana. –

13

subclases no heredan las variables de instancia:

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

En los carriles, atributos heredables proporcionan una solución:

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

atributo Heredable se llevó a cabo principalmente para tratar el problema donde variable de clase rubí se comparte a través la herencia de clase. Considere este ejemplo

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" 

Esto producirá esta salida

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 

Tenga en cuenta que desde los carriles de 3,2 write_inheritable_attribute se ha eliminado. Ver http://dev.mensfeld.pl/2012/01/upgrading-to-rails-3-2-0-from-rails-3-1-3/

Con atributo de clase (lo que solía ser atributo heredable) podemos implementar algo como esto:

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" 

Esto producirá esta salida

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 
Cuestiones relacionadas