请解释这个红宝石的元编程魔法

时间:2014-02-27 13:59:47

标签: ruby metaprogramming

module HashInitialized
  def hash_initialized(*fields)
    define_method(:initialize) do |h|
      missing = fields - h.keys
      raise Exception, "Not all fields set: #{missing}" if missing.any?

  h.each do |k,v|
    instance_variable_set("@#{k}", v) if fields.include?(k) 
    end
   end
 end
end

class Cheese
  extend HashInitialized
  attr_accessor :color, :odor, :taste
  hash_initialized :color, :odor, :taste
end

好的,我明白了:

  1. 我们使用来自HashInitialized的方法扩展了类Cheese,因此从模块HashInitialized中的hash_initialized方法在Cheese中可用作类方法
  2. 我们将3个符号传递给hash_initialized方法
  3. 在hash_initialized方法中,由于* operator
  4. ,这3个符号被放在称为字段的数组中
  5. 在hash_initialized方法中,我们定义了initialize方法
  6. 现在它是我不明白的部分,什么是| h |指的是?为什么我们能够在| h |上调用h.keys。好像是哈希,但我不知道它是如何通过那里的。
  7. 然后我们迭代这个| h |哈希,为了设置实例变量,除了| h |之外,一切都很清楚每个都响应,所以它必须是数组或哈希,我仍然不明白这些值来自何处。
  8. 任何帮助表示赞赏!

    代码取自rubymonk.com,Metaprogramming Ruby:Ascent

1 个答案:

答案 0 :(得分:3)

define_method(:initialize) do |h|...使用一个参数(h)创建了一个initialize方法。这意味着它会创建一个期望哈希的构造函数。想象一下,创建的代码如下所示:

class Cheese

  def initialize(h)
    missing = fields - h.keys
    raise Exception, "Not all fields set: #{missing}" if missing.any?

    h.each do |k,v|
      instance_variable_set("@#{k}", v) if fields.include?(k) 
    end
  end
end