This is the old RCRchive. It's available only for reading and reference. To submit RCRs for Ruby 1.9/2.0, and to participate in discussions about them, please visit the new RCRchive.
ruby picture

RCR 331: Remove 'true' parameter from #attr

Submitted by transami (Wed Apr 12 15:42:57 UTC 2006)

Abstract

I'd like to see the "true" parameter removed from #attr. Either leave it without the ability to create a writer altogether, in which case attr_accessor woud have to be used in it's stay, or allow the attribute/method name to be appended with '=' for that use case. Eg.

  # create reader
  attr :foo
  # create reader and writer
  attr :foo=

Problem

I propose this for two reasons.

First, using a "boolean" parameter like this is not very programmer-friendly b/c it gives no indication of what the parameter does; so it's not nice Literate Programming. This topic has been discussed before on Ruby-talk.

Second and more importantly, the parameter makes it inconvenient to expand on attr's functionality without causing potential compatability issues with other's prior code.

In our specific case in Nitro, we would like to extend #attr to be able to take annotations. Right now we can do this for example:

  attr :x
  ann :x, :default => 10

But we'd like to do:

  attr :x, :default => 10

The boolean parameter on #attr is the only thing preventing a _clean_ extension.

Proposal

Either just remove the 'true' parameter from #attr, or do so and replace it by allowing 'attr :foo=' syntax. This later actually makes a lot of sense since that is exact name of the method it will create anyway.

I've looked at Ruby source and there are only a few places that use the 'true' parameter.

  ext/tk/sample/tcltklib/sample2.rb:      attr :com_disk, TRUE
  ext/tk/sample/tcltklib/sample2.rb:         attr :oval, TRUE
  lib/shell.rb:    attr :cascade, true
  lib/shell.rb:    attr :debug, true
  lib/shell.rb:    attr :verbose, true
  lib/shell.rb:  attr :umask, true
  lib/shell.rb:  attr :record_separator, true
  lib/shell.rb:  attr :verbose, true
  lib/shell.rb:  attr :debug, true
  lib/sync.rb:  attr :sync_mode, true
  lib/sync.rb:  attr :sync_waiting, true
  lib/sync.rb:  attr :sync_upgrade_waiting, true
  lib/sync.rb:  attr :sync_sh_locker, true
  lib/sync.rb:  attr :sync_ex_locker, true
  lib/sync.rb:  attr :sync_ex_count, true
  lib/tracer.rb:    attr :verbose, true
  lib/tracer.rb:    attr :stdout, true
  lib/irb/ruby-token.rb:    attr :name, true
  lib/rdoc/parsers/parse_rb.rb:  attr :skip_space, true
  lib/rdoc/parsers/parse_rb.rb:  attr :read_auto_clean_up, true
  lib/rdoc/parsers/parse_rb.rb:  attr :exception_on_syntax_error, true
  sample/drb/dchats.rb:  attr :name, true

Analysis

Since this interface for #attr is defined in core, only deprecation of its use by Ruby proper can alleviate the problem. And given the nature of the problem, I don't see an other solution but the one(s) presented.

Understandably there is the issue of backwards compatability. But thankfully the feature isn't used extensively; usually attr_accessor is used instead, and updating ones code to take it into account is very simple and straightfoward.

Implementation

Fairly self-explanitory.
ruby picture
Comments Current voting
I would like to see *all* Boolean parameters replaced with expressive methods names (instance_methods(false) being another one that comes to mind. I'm less sold on the attr :foo= thing... it kind of violates the tidiness of just saying :foo and having the automatic syntactic sugar assignment thing. Then again, it only violates it in a way that's invisible when it's actually used.

I would actually think it would make sense for attr to do what attr_accessor does currently. _reader and _writer could then be the specializations.

David Black


I agree with David. It doesn't make sense that attr_writer, attr_reader, and attr_accessor accept multiple attribute names, and attr only accepts one. I think the most common case is attr_accessor, so attr should match that:

 class Foo
   attr :bar, :baz, :bur
 end


I agree with David Black.


I think it would be better either way, thoug I lean toward do less rather then more and just make it the same a attr_reader. I think #attr itself is used rarely enough that 'attr :foo, :foo=' are a fine way to handle both in its case. I also have to confess that I fins myself shying more and more away from these writters and am leaning toward #attr_setter, i.e. where 'foo' would return the value 'foo 42' would set it. I think Ara is on to something here. Obviously thats another reason I think alias :attr :attr_reader --cause otherwise I say alias :attr :attr_setter ;)

T.


I'm with David Black on this one.


i'm simply for replacing attr_accessor with attr - since it's the most commonly used anyway. attr :foo #=> #foo; #foo= attr_reader :foo #=> #foo attr_writer :foo #=> #foo=

i'm less in favor with the use of foo(42) to assign stuff though - i think having = makes the whole thing nice to use (+= comes to mind)


I am not in favour of the originally submitted suggestion; I would rather make attr_accessor and attr aliases for one another, not attr_reader and attr. You would still have special handling for this case if you make it so that "attr :foo, :foo=" does what you're suggesting. --Austin


Hmm... Do you all really use attr_accessor that much? I find I usually only need attr_reader when I think about it. That's why I'd prefer the finer control of attr :foo, :foo=. OTOH, Perhaps a Railsism?

  attr :foo, :writer => true

In anycase, either way is better than no way.

--T.


In anycase, either way is better than no way.

I take that back "alias :attr :attr_accessor" can have bad backward compatability results.

  class X
    def foo=(x)
      ...
    end
    attr :foo
  end

And

  class X
    attr :foo
    def method_missing(sym,*args)
      if /=$/ =~ sym.to_s
        ...
  end

Etc.

T.


I am OK for this proposal, once we can settle down the exact behavioir. Should attr be alias to the attr_accessor, or attr_reader? I think I prefer making it alias to attr_reader, since it encourages encapsulation, which is good. Any opinion?

matz.


I prefer attr_accessor because I *do* use attr_accessor that often. -Austin


That said, as long as one is chosen and documented that way, I see no problem with either one. I will probably continue to use attr_accessor even if attr is made equivalent. What I (personally) would rather not see is "attr :foo=" being meaningful; if attr is going to mean attr_reader, fine. But attr_reader :foo= fails for a meaningful reason. Alternatively, we can look at adopting something like Ara Howard's "traits" library which takes the whole idea to a very interesting level -- I don't use it precisely because it isn't core. -Austin


I agree with Austin, if its documented, it doesnt really matter which one is picked.


"What I (personally) would rather not see is "attr :foo=" being meaningful"

Although, I point out that it is meaningful when aliasing an accessor:

  attr_accessor :a
  alias :b, :a
  alias :b=, :a=

T.


Strongly opposed0
Opposed0
Neutral0
In favor12
Strongly advocate4
ruby picture
ruby picture

Powered by Ruby on Rails.