How to rescue the error exception raised by the `constantize` method?
-
02-07-2021 - |
Question
I am using Ruby on Rails 3.2.2 and I would like to properly rescue the following process flow by raising a "custom" error message:
def rescue_method
# sample_string.class
# => String
# sample_string.inspect
# => "ARubyConstantThatDoesNotExist"
begin
build_constant(sample_string)
rescue
raise("My custom error message: #{build_constant(sample_string)} doesn't exist.")
end
end
def build_constant(sample_string)
"AModule::#{sample_string}".constantize
end
Note: I feel "forced" to use the constantize
method also in the raised "custom" message in order to DRY code...
When the rescue_method
is executed it seems that the raise("My custom error message")
code is never executed and I get the following error:
uninitialized constant AModule::ARubyConstantThatDoesNotExist
How to properly display the raised "custom" message (since a further error exception is raised in the subsequent raised "custom" message)? What do you advice about?
Solution
The problem is that your build_constant
method is doing two things:
- Building the class name.
- Turning the name into a class using
constantize
.
One of those things wants to use the other when an exception is raised. A simple solution is to pull those separate tasks apart:
def build_class_name(sample_string)
"AModule::#{sample_string}"
end
def rescue_method
name = build_class_name(...)
name.constantize
rescue NameError
raise("My custom error message: #{name} doesn't exist.")
end
You should also be more specific about the exception you're looking for so I added that for free.
OTHER TIPS
If you don't want to rely on catching any exception, you could use safe_constantize
(https://apidock.com/rails/ActiveSupport/Inflector/safe_constantize).
Same purpose as constantize
but will return nil
instead, whenever a Module does not exist.
'UnknownModule::Foo::Bar'.safe_constantize # => nil
begin
"AModule::#{sample_string}".constantize
rescue SyntaxError, NameError => err
raise("My custom error message")
end