【问题标题】:How to use class_eval for multi attributes value如何将 class_eval 用于多属性值
【发布时间】:2012-03-06 03:23:15
【问题描述】:

我试图扩展code from this question 以保存属性值的记录。但是,我的代码在多个属性的情况下会失败。这是代码:

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

这里是一个用于测试的虚拟类

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  

由于某种原因,f.barf.bar1 都返回 5f.bar_history = f.bar1_history = [nil, 1, 2, 5]。知道这是为什么吗?

【问题讨论】:

  • #{attr_name}_history 方法的代码在哪里?
  • 糟糕,我没有复制整个代码

标签: ruby


【解决方案1】:

在获取/设置方法时,您使用的是 @ah@attr_name 而不是 @#{ah}@#{attr_name}。这意味着它们总是设置和返回相同的实例变量,而不是不同的、动态命名的变量。

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

我通常还对您的代码进行了一些清理,以使其(我认为)更清晰、更简洁。

【讨论】:

  • 哇。这样可行。非常感谢(也用于清理我的代码:D)。顺便说一句,您可以推荐任何好的简短的 Ruby 介绍书(或教程)吗?我借用了“The ruby​​ programming language”,但有点罗嗦。
  • 请不要忘记accept:)。那本书(又名镐)被认为是权威的 Ruby 书籍,尽管有些人声称它有点密集(我只是零碎地阅读它,所以我不能真正评论太多)。 Why's Poignant Guide to Ruby 也颇受推崇。我的大部分 Ruby 知识来自与他人合作,阅读大量代码,当然,也写了很多。 (也就是说,没有任何简短的教程会涉及到您在这里所做的那种元编程。)
猜你喜欢
  • 2023-03-23
  • 1970-01-01
  • 2011-03-01
  • 2022-01-10
  • 1970-01-01
  • 2014-07-24
  • 2018-09-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多