tags:

views:

52

answers:

1

I'm trying to port a library from ruby 1.8. I didn't write the library. I can change the API if absolutely necessary, but it does have a fair number of users I would prefer not to inconvenience.

Here's the problem simplified:

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

On Ruby 1.8.7p174, this prints 17

On Ruby 1.9.1p243, I get private method ``bar=' called for #<Foo:0x000000010a40f8> (NoMethodError)

Obviously, the Ruby 1.9 behaviour is correct. To better illustrate the Ruby 1.8 bug replace the public with private in the above code. Ruby 1.8 still prints 17!

Therefore I can retain "bug compatibility" with the current version of the library by writing

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

Does anybody have any idea how I can do the right thing and create the appropriate visibility for the attr? On Ruby 1.8 it's going to be public no matter what I do, but is it possible to do the right thing for 1.9?

A: 

If attr_accessor is not doing the right thing for you, you don't need to use it. As far as I know, writing attr_accessor :bar is just a quick way to define two public methods, "bar" and "bar=" that get and set the member variable @bar. So you can do that by hand instead, and add your own customizations and privacy levels to it:

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

  private
  def bar=(value)
    setting_bar_magic()
    @bar=value
  end
end
David Grayson
Am I mis-understanding? Does your library provide "attr_accessor_with_magic" for the user to use, or does it provide a class named Foo with an accessor called "bar"?
David Grayson
the library provides a method called `attr_accessor`. It works the same as Module's `attr_accessor` except that it allows a couple of extra options to be passed.
Bryan Larsen
or at least, it should work the same. But it doesn't -- it cannot preserve the visibility. Thus the question.
Bryan Larsen