class_eval中未初始化的常量

时间:2015-08-01 15:52:29

标签: ruby

我有一个执行class_eval的方法调用:

class BatchRecord < ActiveRecord::Base
  has_one_document :contact
end

这很好用:

def has_one_document(association_name, options={})
  class_eval <<-EOS
      def #{ association_name }
        MongoidContainer::Contact.where(#{ name.underscore }_id: id).first
      end
  EOS
end

但下面给出了“未初始化的常量BatchRecord :: Contact”:

def has_one_document(association_name, options={})
  class_eval <<-EOS
      def #{ association_name }
        MongoidContainer.const_get(#{association_name.to_s.classify}).where(#{ name.underscore }_id: id).first
      end
  EOS
end

我无法理解为什么它应该生成BatchRecord :: Contact时应该生成MongoidContainer :: Contact。我做错了什么?

1 个答案:

答案 0 :(得分:2)

固定代码:

def has_one_document(association_name, options={})
  class_eval <<-EOS
    def #{ association_name }
      MongoidContainer.const_get(#{association_name.to_s.classify.inspect})
        .where(#{ name.underscore }_id: id).first
    end
  EOS
end

请注意第4行添加的.inspect

classify returns a string,所以你的中间线会扩展到

MongoidContainer.const_get(Contact).where # ...

这会尝试在当前作用域(您的Contact类)中搜索名为BatchRecord的常量,该常量失败。 const_get需要一个字符串,因此您需要inspect字符串才能将其放入eval(或class_eval)。