2

I tried to to extend the code from this question for keeping records of an attribute value. However, my code fails in the case of more than one attributes. Here is the code:

class Class
  def attr_accessor_with_history(attr_name)
    attr_name = attr_name.to_s
    attr_reader attr_name

    ah=attr_name+"_history"
    attr_reader ah 

    class_eval %Q{          
      def #{attr_name}= (attr_name)
        @attr_name=attr_name

        if @ah == nil
          @ah=[nil]
        end
        @ah.push(attr_name)
      end
      def #{ah}
        @ah
      end  

      def #{attr_name}
        @attr_name
      end
     }
  end
end

Here a dummy class for testing

class Foo
  attr_accessor_with_history :bar
  attr_accessor_with_history :bar1
end

f = Foo.new
f.bar = 1
f.bar = 2
f.bar1 = 5
p f.bar_history  
p f.bar1_history  

For some reason, f.bar and f.bar1 both return 5 and f.bar_history = f.bar1_history = [nil, 1, 2, 5]. Any idea why that is?

Community
  • 1
  • 1

1 Answers1

2

You were using @ah and @attr_name instead of @#{ah} and @#{attr_name} when getting/setting in the methods. This meant that they were always setting and returning the same instance variable, instead of different, dynamically named ones.

class Class
  def attr_accessor_with_history(attr_name)
    class_eval %{
      attr_reader :#{attr_name}, :#{attr_name}_history

      def #{attr_name}=(value)
        @#{attr_name} = value
        @#{attr_name}_history ||= [nil]
        @#{attr_name}_history << value
      end
     }
  end
end

I've also generally cleaned up your code a little to make it (I think) clearer and more concise.

Andrew Marshall
  • 95,083
  • 20
  • 220
  • 214
  • Wow. that works. Thanks a bunch (for cleaning my code also :D). By the way, is there any good and short intro book to Ruby (or tutorial) that you can recommend? I borrowed "The ruby programming language" but it is kinda wordy. – user1249263 Mar 06 '12 at 05:19
  • 1
    Please don't forget to [accept](http://meta.stackexchange.com/a/5235/158402) `:)`. And that book (aka the pickaxe) is considered to be the definitive Ruby book, though some claim it to be a bit dense (I've only read it in piecemeal so I can't really comment too much). [Why's Poignant Guide to Ruby](http://mislav.uniqpath.com/poignant-guide/) is also quite revered. Most of my Ruby knowledge comes from working with others and reading lots and lots of code and, of course, writing a lot too. (That said, no short tutorial will get into the sort of metaprogramming you're doing here.) – Andrew Marshall Mar 06 '12 at 05:26