Ruby.Metaprogramming. class_eval

前端 未结 5 685
孤独总比滥情好
孤独总比滥情好 2020-12-18 16:50

There seem to be a mistake in my code. However I just can\'t find it out.

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


        
5条回答
  •  别那么骄傲
    2020-12-18 17:33

    You shouldn't be opening Class to add new methods. That's what modules are for.

    module History
      def attr_accessor_with_history(attr_name)
        attr_name = attr_name.to_s
    
        attr_accessor attr_name
    
        class_eval %Q{
          def #{attr_name}_history
            [1, 2, 3]
          end
        }
    
      end
    end
    
    class Foo
      extend History
      attr_accessor_with_history :bar
    end
    
    f = Foo.new
    f.bar = 1
    f.bar = 2
    puts f.bar_history.inspect
    # [1, 2, 3]
    

    And here's the code you probably meant to write (judging from the names).

    module History
      def attr_accessor_with_history(attr_name)
        attr_name = attr_name.to_s
    
        class_eval %Q{
          def #{attr_name}
            @#{attr_name}
          end
    
          def #{attr_name}= val
            @#{attr_name}_history ||= []
            @#{attr_name}_history << #{attr_name}
    
            @#{attr_name} = val
          end
    
          def #{attr_name}_history
            @#{attr_name}_history
          end
        }
    
      end
    end
    
    class Foo
      extend History
      attr_accessor_with_history :bar
    end
    
    f = Foo.new
    f.bar = 1
    f.bar = 2
    puts f.bar_history.inspect
    # [nil, 1]
    

提交回复
热议问题