Rails 2.1 and const_missing

167 views
Skip to first unread message

Phillip Koebbe

unread,
Sep 20, 2008, 9:51:26 PM9/20/08
to Dr Nic's Magic Models
I was using MMC in a rake task in Rails 2.0.2 successfully, but when I
recently upgraded to Rails 2.1.1, the rake task failed with the error

uninitialized constant {const_id}

A little bit of digging turned up a couple of things.

1) There is a type in connected.rb at line 20:

raise NameError.new("uninitialized constant \{const_id}") unless
target_class

Notice the backslash where a pound should be. The reason this was
never found was because

2) ActiveSupport::Inflector.constantize was changed between 2.0.2 and
2.1 such that const_missing is actually called now. In 2.0.2, it was
defined as

def constantize(camel_cased_word)
unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ camel_cased_word
raise NameError, "#{camel_cased_word.inspect} is not a valid
constant name!"
end

Object.module_eval("::#{$1}", __FILE__, __LINE__)
end

Notice that it's doing a regex match on the format of camel_case_word,
not really checking to see if it exists. In 2.1, it's defined as

def constantize(camel_cased_word)
names = camel_cased_word.split('::')
names.shift if names.empty? || names.first.empty?

constant = Object
names.each do |name|
constant = constant.const_defined?(name) ?
constant.const_get(name) : constant.const_missing(name)
end
constant
end

Notice here that if the constant is not defined, the object's
const_missing method will be called, which brings us back to
connected.rb. Since in 2.0.2 const_missing didn't get called, I
figured it probably wouldn't hurt to just return if the const doesn't
exist, so I changed

raise NameError.new("uninitialized constant #{const_id}") unless
target_class

to

return unless target_class

I then ran my rake task in Rails 2.1.1 and it seemed to work
correctly. I don't know if this is appropriate or not, but hey it
seems to work.

Peace,
Phillip
Reply all
Reply to author
Forward
0 new messages