C'mon, this is ruby! Revel in it!

class Shape
  attr_reader :details
  def self.keys
    [:size, :fill_color, :line_color, :line_color]
  end

  def initialize
    @details = {}
    self.class.keys.each {|key| @details[key] = "" }
  end

  keys.each do |key|
    define_method key do
      @details[key]
    end

    define_method "#{key}=" do |input|
      @details[key] = input
    end
  end
end

my_shape = Shape.new

shape_details = {
 :size => 'small',
 :fill_color => 'red',
 :line_color => 'black',
 :line_width => '2'
}

my_shape.details.merge!(shape_details)


On Fri, Oct 29, 2010 at 10:31 PM, Jeremy Bopp <jeremy / bopp.net> wrote:

> On 10/29/2010 09:14 PM, Greg Willits wrote:
> > If I need to dynamically reference instance vars, is this the only way
> > to do it (var set example)?
> >
> >   my_object.send(:instance_variable_set, "@#{iname}", ivalue)
> >
> > I expected something more elegant, but this is the only way I can get it
> > to work. No biggie, just curious.
> >
> > More complete example below.
> >
> > -- gw
> >
> >
> > class Shape
> >   attr_accessor :size, :fill_color, :line_color, :line_width
> >   def initialize
> >     @size = ""
> >     @fill_color = ""
> >     @line_color = ""
> >     @line_width = ""
> >   end
> > end
> >
> > my_shape = Shape.new
> >
> > shape_details = {
> >   :size => 'small',
> >   :fill_color => 'red',
> >   :line_color => 'black',
> >   :line_width => '2'}
> >
> > shape_details.each do |iname, ivalue|
> >   my_shape.send(:instance_variable_set, "@#{iname}", ivalue)
> > end
>
> How about backing the accessors with a hash that also has an accessor?
> That way you could merge in a hash of settings or set/get them neatly by
> name:
>
> class Shape
>  attr_reader :details
>
>  def initialize
>    @details = {
>       :size => "",
>      :fill_color => "",
>      :line_color => "",
>      :line_width => ""
>    }
>  end
>
>   def size
>    @details[:size]
>  end
>
>  def size=(size)
>    @details[:size] = size
>  end
>
>  def fill_color
>    @details[:fill_color]
>  end
>
>  def fill_color=(fill_color)
>    @details[:fill_color] = fill_color
>  end
>
>  def line_color
>    @details[:line_color]
>  end
>
>  def line_color=(line_color)
>    @details[:line_color] = line_color
>  end
>
>  def line_width
>    @details[:line_width]
>  end
>
>  def line_width=(line_width)
>    @details[:line_width] = line_width
>   end
> end
>
> my_shape = Shape.new
>
> shape_details = {
>  :size => 'small',
>  :fill_color => 'red',
>  :line_color => 'black',
>  :line_width => '2'
> }
>
> my_shape.details.merge!(shape_details)
>
>
> -Jeremy
>
>