Donato
Donato

Reputation: 2777

uninitialized constant in class_eval

I have a method call that does a class_eval:

class BatchRecord < ActiveRecord::Base
  has_one_document :contact
end

This works fine:

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

But this below gives me "uninitialized constant 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

I cannot understand why it is producing BatchRecord::Contact when it should be producing MongoidContainer::Contact. What am I doing wrong?

Upvotes: 0

Views: 421

Answers (1)

tckmn
tckmn

Reputation: 59273

Fixed code:

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

Note the added .inspect on line 4.

classify returns a string, so your middle line would expand to

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

This tries to search for a constant named Contact in the current scope (your BatchRecord class), which fails. const_get takes a string, so you have to inspect your string before putting it in an eval (or class_eval).

Upvotes: 2

Related Questions