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
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