Const_get vs. constantize

Is there any reason to use rails’ constantize instead of ruby’s const_get to look up a class given its name? Constantize is more complicated, and the documentation didn’t make it clear what that complexity is for.

The docs refer to the fact that:

The name is assumed to be the one of a top-level constant

E.g.:

class Thing
end

class User
  class Thing
  end

  const_get("Thing") # => returns User::Thing
  "Thing".constantize # => returns ::Thing
end

Which is usually what you want when dealing with strings that represent models.

Another way in which it is useful is that it’s a method on String, so it fits nicely with the other methods that you can chain:

"user/things".singularize.camelize.constantize # => User::Thing
1 Like

Thanks for the explanation. Would sticking “::” on the front of the string to const_get, if not already present, then be equivalent (except for the chaining)?

Looking at the code there’s actually another edge case that is covered by constantize where const_get's behavior is a bit weird:

Object.const_get("::User::User::User") => User
"::User::User::User" => NameError: uninitialized constant User

Odd, I get the NameError from both cases.

Did you have a User class, though?

Try the following:

class Example
end

Object.const_get("::Example::Example::Example").name # => "Example"

This does not raise for me using Ruby 2.5.7.

Must be different in 2.6.

$ cat test.rb
class Example
end

Object.const_get("::Example::Example::Example").name

$ ruby test.rb
Traceback (most recent call last):
	1: from test.rb:4:in `<main>'
test.rb:4:in `const_get': uninitialized constant Example::Example (NameError)

$ ruby --version
ruby 2.6.6p146 (2020-03-31 revision 67876) [x86_64-darwin19]

Indeed! I also get an exception on 2.6 & 2.7. Didn’t know that this changed, good to know :slight_smile: