Запись наследуемого атрибута против базового назначения в Rails - PullRequest
7 голосов
/ 28 ноября 2010

Просто любопытно, в чем разница между этими двумя в гемах Rails:

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

Я не смог найти хорошую документацию по write_inheritable_attribute, просто читал какой-то источник гемов и нашелбывший использовал несколько раз.Спасибо!

Ответы [ 3 ]

13 голосов
/ 13 декабря 2010

Подклассы не наследуют переменные экземпляра:

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

В рельсах наследуемые атрибуты предоставляют решение:

>> class B ; end
>> B.write_inheritable_attribute(:candy, 7) # => 7
>> class C < B ; end
>> C.read_inheritable_attribute(:candy)     # => 7
5 голосов
/ 29 ноября 2010

Для простого класса или модуля разница не будет, но с более сложными модулями, которые могут быть загружены с несколькими другими модулями, такие методы, как write_inheritable_attribute, могут помочь вам легко и надежно изменять объекты, не беспокоясь ообласть действия, частные / защищенные методы и всевозможные помехи от магии рубинового метапрограммирования, такие как method_missing.

Короче говоря, когда вы пишете foo.sample = "sample", все, что может произойти до, после или вместо установки атрибута, особенно если объект использует ActiveModel или ORM.Когда вы используете foo.write_inheritable_attribute(:sample, "sample"), вы получаете гораздо больший контроль над тем, что происходит.

2 голосов
/ 01 марта 2013

Атрибут Inheritable был реализован в основном для решения проблемы, когда переменная класса ruby ​​является общей для наследования классов.Рассмотрим этот пример

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"

Это приведет к выводу

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

Обратите внимание, что начиная с Rails 3.2 был удален write_inheritable_attribute.См. http://dev.mensfeld.pl/2012/01/upgrading-to-rails-3-2-0-from-rails-3-1-3/

С помощью атрибута класса (который раньше был наследуемым атрибутом) мы можем реализовать что-то вроде этого:

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"

Это приведет к выводу

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...