Forum: Ruby my attr_accessor

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
8bb088c70909f7fed70f1cd10edf80cb?d=identicon&s=25 cibercitizen1 (Guest)
on 2008-11-24 22:45
(Received via mailing list)
I tried to

class Foo
   attr_accessor  :bar1, :bar2

  def initialize( &bloc )
   instance_eval( &bloc )
  end
end

and then

f = Foo.new {
 bar1 = 12345
 bar2 = 44444
}

but this doesn't work
unless you write @bar1=12345 in the block, as
Ruby does not consider bar1= a method call but an assignment.

Here's my solution. Any comments?

#--------------------------------
module MyAccessor
  def my_attr (nou, defval=nil)
    class_eval "
      def #{nou} (s=nil)
        @#{nou} = s || @#{nou} || '#{defval}'
      end
      "
  end # def my_attr
end # module

#--------------------------------
class Foo

  extend MyAccessor

  my_attr(:title, "default title")
  my_attr(:height, 100)
  my_attr(:color, 'black')

  def initialize( &bloc )
    instance_eval( &bloc )
  end # def

  def show
    puts "attributes ----------"
    puts "title="+ title.to_s
    puts "color="+ color.to_s
    puts "height="+ height.to_s
  end

end

#----------------------------------
#----------------------------------
fo = Foo.new() {
  color "red"
  height 50
}

puts "---------------------------"
fo.show

puts "---------------------------"
fo.color("blue")
puts fo.color

puts "---------------------------"
fo.show
Cec345a59245af9d06e4438a413f4eb5?d=identicon&s=25 Shot (Piotr Szotkowski) (Guest)
on 2008-11-24 23:22
(Received via mailing list)
cibercitizen1:

> I tried to

> class Foo
>    attr_accessor  :bar1, :bar2
>
>   def initialize( &bloc )
>    instance_eval( &bloc )
>   end
> end

> and then

> f = Foo.new {
>  bar1 = 12345
>  bar2 = 44444
> }

> but this doesn't work
> unless you write @bar1=12345 in the block, as
> Ruby does not consider bar1= a method call but an assignment.

Right, unless you precede it with self:

f = Foo.new {
  self.bar1 = 12345
  self.bar2 = 44444
}

-- Shot
E088bb5c80fd3c4fd02c2020cdacbaf0?d=identicon&s=25 Jesús Gabriel y Galán (Guest)
on 2008-11-25 09:06
(Received via mailing list)
On Mon, Nov 24, 2008 at 11:17 PM, Shot (Piotr Szotkowski) <shot@hot.pl>
wrote:
>> end
>
>> and then
>
>> f = Foo.new {
>>  bar1 = 12345
>>  bar2 = 44444
>> }
>
>> but this doesn't work

> Right, unless you precede it with self:
>
> f = Foo.new {
>  self.bar1 = 12345
>  self.bar2 = 44444
> }
>

Another idiom is to yield self to the block like so:

irb(main):001:0> class Foo
irb(main):002:1> attr_accessor :bar1, :bar2
irb(main):003:1> def initialize
irb(main):004:2> yield self
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> f = Foo.new {|foo| foo.bar1 = "test"; foo.bar2 =
"test2"}
=> #<Foo:0xb7b72dcc @bar2="test2", @bar1="test">

Jesus.
8bb088c70909f7fed70f1cd10edf80cb?d=identicon&s=25 cibercitizen1 (Guest)
on 2008-11-25 23:05
(Received via mailing list)
My solution above for having

fo = Foo.new() {
  color "red"
  height 50
}

by defining

class Foo
  extend MyAccessor

  my_attr(:title, "default title")
  my_attr(:height, 100)
  my_attr(:color, 'black')
  def initialize( &bloc )
    instance_eval( &bloc )
  end # def
end # class

is buggy because the ' ' in
@#{nou} = s || @#{nou} || '#{defval}'
ends with variables being always strings.

This one works better

module MyAccessor
  def my_attr (nou, defval=nil)
    if defval == nil
      code ="def #{nou} (s=nil)
        @#{nou} = s || @#{nou}
      end"
    elsif defval.class==String
      code ="def #{nou} (s=nil)
        @#{nou} = s || @#{nou} || '#{defval}'
      end"
    else
      code ="def #{nou} (s=nil)
        @#{nou} = s || @#{nou} || #{defval}
      end"
    end
    #puts "class_eval", code
    class_eval code
  end # def my_attr
end # module
This topic is locked and can not be replied to.