1.9 warning for 'private' and possible bug

  • Thread starter Joel VanderWerf
  • Start date
J

Joel VanderWerf

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 method `x=' 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 method `x=' called for
#<C:0x000000012e5670> (NoMethodError)


Does anyone understand this warning? Is 'private' (without an argument)
deprecated?
 
J

Joel VanderWerf

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 method `x=' 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 method `x=' called for
#<C:0x000000012e5670> (NoMethodError)


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

Rein said:
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.
 
J

Joel VanderWerf

Rein said:
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.
 
L

Luis Lavena

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 method `x=' 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 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.
 
J

Joel VanderWerf

Luis said:
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 method `x=' 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 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.

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 method `x=' called for
#<C:0x00000001e40858> (NoMethodError)
 
J

Joel VanderWerf

Luis said:
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 method `x=' called for
#<C:0x00000002442148> (NoMethodError)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top