在类定义期间添加实例方法

时间:2013-05-18 00:28:35

标签: ruby-on-rails ruby activerecord metaprogramming

我目前正在研究我的第一个宝石并开始我的元编程经验。

因此,我想要一些关于如何在类定义中正确定义实例方法的反馈。

具体来说,我创建了这个模块,您应该在ActiveRecord模型中extend,如下所示:

class Duck < ActiveRecord::Base
  extend UnitedAttributes::Model
  attr_accessible :name, :weight
  unite :weight, :kilogram
end

以下是UnitedAttribues::Model模块的来源。 https://github.com/nielsbuus/united_attributes/blob/master/lib/united_attributes/model.rb

这是一个缩短版本,没有多余的代码:

module UnitedAttributes
  module Model

    def unite(accessor, unit, options = {})    
      class_eval do
        define_method "united_#{accessor}" do
          Attribute.new(self.send(accessor), options)
        end
      end
    end

  end
end

它似乎有用,但我有一些顾虑:

  1. class_eval这里使用的是正确的方法吗?
  2. define_method这里使用的是正确的方法吗?
  3. 将选项哈希传递给类方法,并在实例方法体内使用。这样安全吗?有任何记忆问题吗?

1 个答案:

答案 0 :(得分:0)

如果你可以使用ActiveSupport::Concern,那将是一种标准化的方式。

如果没有,你总是可以做类似的事情。

我不担心内存问题。一般来说,散列很小。我担心的是,如果通过这些选项的来电者不知道你会坚持他们。例如:

options = { :foo => 'var', :bar => 'example' }

unite :name_1, :unit_a, options

options.delete(:example)

unite :name_2, :unit_b, options

在这种情况下,options哈希的修改会无意中影响。解决此问题的一种方法是向dupclone传入选项,或者更好,选择所需的值,并在收到未知参数时引发异常。 options哈希不应被视为unite方法的属性。

如果来电者传递了frozen个选项,您也会遇到麻烦。您拨打merge!会产生异常。通常,操纵传入方法的参数被认为是不好的形式,除非该方法专门用于执行这种功能。