From: redmine.ruby-lang.org@... Date: 2015-02-05T19:39:02+00:00 Subject: [ruby-core:68028] [ruby-trunk - Feature #8564] Extend Module#attr... methods Issue #8564 has been updated by Tyler Rick. I would love to see this added to Ruby too, so that I don't have to repeat myself by **defining** attributes in one place and then **initializing** them later in `initialize` (as discussed in #5825 and #8563). In the meantime, however, I've come across the [fattr](https://github.com/ahoward/fattr) gem, which does exactly the same thing (plus a few extra things like defining a `foo!` method to *re-initialize*; I don't think `attr_reader` should do those extra things). (By the way, there was a great [RubyTapas episode](http://www.rubytapas.com/episodes/276-Fattr) (subscription required) about fattr that got me excited about using it.) Note that it's possible to support *both* initializing an attribute **to a Proc** *and* using a block to initialize a attribute **to an expression** that is evaluated during object initialization. Here's how [fattr](https://github.com/ahoward/fattr) solves that problem... If you pass a block to `fattr`, it is evaluated during initialization: ~~~ruby class C fattr foo: 42 fattr(:foo_2) { foo * 2 } # evaluated during initialization fattr(:time) { Time.now } # evaluated during initialization end p C.new.foo #=> 42 p C.new.foo_2 #=> 84 p C.new.time #=> 2015-02-05 ... ~~~ ... whereas if you pass a block as the **value** for a hash key, it leaves it as a Proc and doesn't evaluate it: ~~~ruby class C fattr my_proc: ->{ 'my_proc' } end p C.new.my_proc #=> #<Proc:0x0...> p C.new.my_proc.() #=> 'my_proc' ~~~ I can't think of any downside to supporting the block behavior for `attr_accessor`. It doesn't appear that the block syntax of `attr_accessor` is used for anything currently... ~~~ruby class C2 attr_accessor(:foo_2) { foo * 2 } # The block is never called end c = C2.new p c.foo_2 #=> nil ~~~ Otherwise, you would be forced to add an `initialize` method any time you needed to initialize something to an expression that needed to be evaluated *at initialization time*, which would require duplication and mixing of initialization methods, which I think should be avoided: ~~~ruby class C fattr foo: 42 attr_accessor :foo_2 def initialize @foo_2 = foo * 2 end end p C.new.foo #=> 42 p C.new.foo_2 #=> 84 ~~~ ---------------------------------------- Feature #8564: Extend Module#attr... methods https://bugs.ruby-lang.org/issues/8564#change-51414 * Author: Boris Stitnicky * Status: Open * Priority: Normal * Assignee: ---------------------------------------- Extend #attr_reader, #attr_writer, #attr_accessor syntax to accept default values, such as: attr_reader foo: 42, bar: 43 Possibility of closures evaluated at initialization time might also be considered: attr_reader baz: -> { Time.now }, quux: 42 -- https://bugs.ruby-lang.org/