Project

General

Profile

Actions

Feature #6470

closed

Make attr_accessor return the list of generated method

Feature #6470: Make attr_accessor return the list of generated method

Added by rupert (Robert Pankowecki) over 13 years ago. Updated over 4 years ago.

Status:
Closed
Target version:
-
[ruby-core:45144]

Description

attr_accesor currently returns nil. It would be more helpful if it return list of generated methods so that it can become an argument to other methods like :private or :protected. That way private accessors can still be defined at top of the class and be private without changing the visibility of next methods.

class Something private *attr_accessor :user, :action # IMHO This is nice # private attr_accessor :user, :action # <-- would be even better if :private method accepted arrays def initialize(user, action) self.user = user self.action = action end def public_method user.do_something(action) end end 

VS

class Something private; attr_accessor :user, :action; public # IMHO Hack!! def initialize(user, action) self.user = user self.action = action end def public_method user.do_something(action) end end 

VS

class Something def initialize(user, action) self.user = user self.action = action end def public_method user.do_something(action) end private attr_accessor :user, :action # IMHO Does not look nice at bottom of the class definition end 

Related issues 4 (1 open3 closed)

Updated by henry.maddocks (Henry Maddocks) over 13 years ago Actions #1 [ruby-core:45145]

Aren't accessors public by definition? If you want them to be private use attr.

Updated by shevegen (Robert A. Heiler) over 13 years ago Actions #2 [ruby-core:45147]

Yes, they are public.

If I understood them correctly, they are the same as this in pure ruby code:

attr_accessor :foo def foo @foo end def foo=(i) @foo = i end 

I found that I personally only need attr_reader, attr_writer and attr_accessor.
I have not found a use case for attr alone yet.

Updated by mame (Yusuke Endoh) over 13 years ago Actions #3 [ruby-core:45166]

  • Status changed from Open to Assigned
  • Assignee set to matz (Yukihiro Matsumoto)

This duplicates #6198.

BTW, why don't you use instance variables directly? That is:

class Something def initialize(user, action) @user = user @action = action end def public_method @user.do_something(@action) end end 

--
Yusuke Endoh

Updated by rupert (Robert Pankowecki) over 13 years ago Actions #4 [ruby-core:45173]

I want to access my private fields also via methods instead of directly via instance variables so refactoring in future is easier. For example instead of finding in class all occurrences of @var = something and changing them into either "@var = something.strip" or extracting it into setter, I already use the private setter defined with attr_accessor everywhere. That way I only need to change the setter implementation in one place and don't need to look for code setting instance variable because there is non such, only calls for the accessor.

Updated by mame (Yusuke Endoh) almost 13 years ago Actions #5

  • Target version set to 2.6

Updated by naruse (Yui NARUSE) almost 8 years ago Actions #6

  • Target version deleted (2.6)

Updated by matz (Yukihiro Matsumoto) almost 7 years ago Actions #7

  • Status changed from Assigned to Rejected

There's no use for private attr_reader, attr_writer, etc.
And protected is not encouraged enough for new features. So I reject this.

Matz.

Updated by Eregon (Benoit Daloze) almost 7 years ago Actions #8 [ruby-core:90984]

  • Status changed from Rejected to Open

@matz (Yukihiro Matsumoto) There are use cases, see https://bugs.ruby-lang.org/issues/11539 and https://bugs.ruby-lang.org/issues/11541.

Also, one case which has been IIRC frequently requested (mentioned just above in this issue, https://bugs.ruby-lang.org/issues/6470#note-4) is:

attr_reader :foo private attr_writer :foo 

So one can use the symmetric foo and foo= in the class, but only the getter would be public.
This is also useful to evolve foo= (e.g., to invalidate some caches if set) and add extra logic in it, without having to change all places from @foo = to self.foo =.

I reopen because I think not all relevant issues have been considered.

In general, I support this feature as it is a general and composable extension which enables many more things such as for def (decorators, debugging, concurrency, etc).

Updated by Eregon (Benoit Daloze) almost 7 years ago Actions #9

  • Related to Feature #11539: Support explicit declaration of volatile instance variables added

Updated by Eregon (Benoit Daloze) almost 7 years ago Actions #10

  • Related to Feature #11541: Let attr_accessor, _reader & _writer return symbols of the defined methods added

Updated by phluid61 (Matthew Kerwin) almost 7 years ago Actions #11 [ruby-core:90989]

In general I support this request, but in this proposed use-case ...

attr_reader :foo private attr_writer :foo 

So one can use the symmetric foo and foo= in the class, but only the getter would be public.
This is also useful to evolve foo= (e.g., to invalidate some caches if set) and add extra logic in it, without having to change all places from @foo = to self.foo =.

foo= without @ or self. will assign a local variable. You'd have to change it to foo=(...) or send :foo=, ... anyway, no?

Updated by rupert (Robert Pankowecki) almost 7 years ago Actions #12 [ruby-core:90999]

There's no use for private attr_reader, attr_writer, etc.

The intended usage is to ease future refactorings. If you always start with a method then later you can easily redefine just the method.

Initial code

class Something private attr_accessor :x, :y def something(a) self.x = a + y end end 

Code after refactoring:

class Something private attr_accessor :y private attr_reader :x def something(a) self.x = a + y end private def x=(new_value) @x_set_at = Time.now @x = new_value end 

Notice that nothing setting @x had to be refactored because @x variable was always changed via the self.x= setter.

So when the time comes and cache expiration or additional logic needs to be added, makes it easy to just redefine the setter or getter with additional logic.

That's why I always prefer to use private accessors instead of instance variables. They are more flexible.

Updated by hsbt (Hiroshi SHIBATA) almost 7 years ago Actions #13

  • Description updated (diff)

Updated by k0kubun (Takashi Kokubun) over 4 years ago Actions #15

  • Related to Feature #17314: Provide a way to declare visibility of attributes defined by attr* methods in a single expression added

Updated by k0kubun (Takashi Kokubun) over 4 years ago Actions #16

  • Status changed from Open to Closed
Actions

Also available in: PDF Atom