сохранение видимости при выполнении alias_method_chain на attr_accessor в Ruby 1.9 - PullRequest
0 голосов
/ 27 ноября 2009

Я пытаюсь портировать библиотеку с ruby ​​1.8. Я не писал в библиотеке. Я могу изменить API, если это абсолютно необходимо, но у него довольно много пользователей, и я бы предпочел не причинять неудобств.

Вот упрощенная проблема:

require 'rubygems'
require 'activesupport'

class Foo
  private
  def self.attr_accessor_with_magic(*attrs)
    attr_accessor_without_magic(*attrs)
  end

  public
  class << self
    alias_method_chain :attr_accessor, :magic
  end

  attr_accessor :bar
end

foo=Foo.new
foo.bar=17
puts foo.bar

На Ruby 1.8.7p174 печатается 17

На Ruby 1.9.1p243 я получаю private method ``bar=' called for #<Foo:0x000000010a40f8> (NoMethodError)

Очевидно, что поведение Ruby 1.9 является правильным. Чтобы лучше проиллюстрировать ошибку Ruby 1.8, замените public на private в приведенном выше коде. Ruby 1.8 все еще печатает 17!

Поэтому я могу сохранить «совместимость с ошибками» с текущей версией библиотеки, написав

  private
  def self.attr_accessor_with_magic(*attrs)
    public
    attr_accessor_without_magic(*attrs)
    private
  end

Кто-нибудь знает, как я могу поступить правильно и создать соответствующую видимость для атрибута? На Ruby 1.8 это будет public независимо от того, что я делаю, но возможно ли сделать правильную вещь для 1.9?

1 Ответ

0 голосов
/ 27 ноября 2009

Если attr_accessor не подходит для вас, вам не нужно его использовать. Насколько я знаю, написание attr_accessor :bar - это просто быстрый способ определить два открытых метода, "bar" и "bar =", которые получают и устанавливают переменную-член @bar. Таким образом, вместо этого вы можете сделать это вручную и добавить свои собственные настройки и уровни конфиденциальности:

class Foo
  public
  def bar
    reading_bar_magic()
    return @bar
  end

  private
  def bar=(value)
    setting_bar_magic()
    @bar=value
  end
end
...