1.9 warning for 'private' and possible bug

Consider this error:

$ cat t.rb
module M
private
def attr_accessor(*args); super; end
end

class C
extend M
attr_accessor :x
end

C.new.x = 1

$ ruby19 t.rb
t.rb:11:in <main>': private methodx=’ called for
#<C:0x0000000091c670> (NoMethodError)

That looks very suspect, so I was about to file a bug report. But then I
noticed that there is a warning reported with the -v switch:

$ ruby19 -v t.rb
ruby 1.9.2dev (2010-05-31) [x86_64-linux]
t.rb:3: warning: private attribute?
t.rb:11:in <main>': private methodx=’ called for
#<C:0x000000012e5670> (NoMethodError)

Does anyone understand this warning? Is ‘private’ (without an argument)
deprecated?

This behavior seems consistent with, for instance:

class PrivateAccessor
private
attr_accessor :foo
end

PrivateAccessor.new.foo

=> NoMethodError: private method `foo’ called for

#PrivateAccessor:0x1017bbce8

On 2010-06-05 15:25:59 -0700, Joel VanderWerf said:

class C

Does anyone understand this warning? Is ‘private’ (without an argument)
deprecated?

Rein H. wrote:

This behavior seems consistent with, for instance:

class PrivateAccessor
private
attr_accessor :foo
end

PrivateAccessor.new.foo

=> NoMethodError: private method `foo’ called for

#PrivateAccessor:0x1017bbce8

No. The original code is controlling access to the method
Module#attr_accessor. Your code is controlling access to
PrivateAccessor#foo.

On 2010-06-05 15:55:20 -0700, Joel VanderWerf said:

No. The original code is controlling access to the method
Module#attr_accessor. Your code is controlling access to
PrivateAccessor#foo.

Not exactly. Methods created by attr_accessor will have its visibility.
Your code makes attr_accessor private, which is why accessors created
with it are also private. You can also demonstrate by writing your own
attr_accessor from scratch.

Rein H. wrote:

On 2010-06-05 15:55:20 -0700, Joel VanderWerf said:

No. The original code is controlling access to the method
Module#attr_accessor. Your code is controlling access to
PrivateAccessor#foo.

Not exactly. Methods created by attr_accessor will have its visibility.
Your code makes attr_accessor private, which is why accessors created
with it are also private. You can also demonstrate by writing your own
attr_accessor from scratch.

Did you try that? The following code runs the same in 1.8 and 1.9:

class C
class << self
def my_attr_accessor(name)
define_method name do
puts “foo”
end
end
private :my_attr_accessor
end

 my_attr_accessor :bar

end

C.new.bar # => foo

Anyway, attr_accessor is already a private module method in ruby, but
the instance methods it creates are not, by default.

On 2010-06-05 17:02:17 -0700, Joel VanderWerf said:

Anyway, attr_accessor is already a private module method in ruby, but
the instance methods it creates are not, by default.

I stand corrected. Interesting.

On Jun 5, 6:25 pm, Joel VanderWerf [email protected] wrote:

attr_accessor :x

$ ruby19 -v t.rb
ruby 1.9.2dev (2010-05-31) [x86_64-linux]
t.rb:3: warning: private attribute?
t.rb:11:in <main>': private method x=’ called for
#<C:0x000000012e5670> (NoMethodError)

Does anyone understand this warning? Is ‘private’ (without an argument)
deprecated?

Maybe is because you’re setting private for all the following methods,
including the ones that attr_accessor defines moving forward after the
“extending”?

if you change the private to ‘private :attr_accessor’ there is no
warning and things works.

Luis L. wrote:

extend M
noticed that there is a warning reported with the -v switch:
Maybe is because you’re setting private for all the following methods,
including the ones that attr_accessor defines moving forward after the
“extending”?

if you change the private to ‘private :attr_accessor’ there is no
warning and things works.

True. However:

$ cat t.rb
module M
private
def attr_accessor(*args); super; end
public # <-- added this line
end

class C
extend M
attr_accessor :x
end

C.new.x = 1

$ ruby t.rb
$ ruby19 t.rb
t.rb:12:in <main>': private methodx=’ called for
#<C:0x00000001e40858> (NoMethodError)

Luis L. wrote:

Maybe is because you’re setting private for all the following methods,
including the ones that attr_accessor defines moving forward after the
“extending”?

That’s probably true in some sense (some state is getting set and
affecting the methods defined by attr_accessor), but it’s not setting
other methods private:

$ cat t.rb
module M
private
def attr_accessor(*args); super; end
end

class C
extend M
def m; puts “m”; end
attr_accessor :x
end

C.new.m
C.new.x = 1

$ ruby19 t.rb
m
t.rb:13:in <main>': private methodx=’ called for
#<C:0x00000002442148> (NoMethodError)