Is it possible to throw exception during macro expansion? What I want to do is to check whether a method exists within a class that I passed in, so the error get caught during compile time.
I want to be able to do something like this. If my controller does not implement that action, it will be caught during compiled time instead of run time.
{% for verb in RESOURCES %}
macro {{verb.id}}(resource, controller, action)
{% raise "Action not found" unless controller.responds_to?(:"#{action.to_s}" %}
route {{verb}}, \{{resource}}, \{{controller}}, \{{action}}
end
{% end %}
Raise does work fine in macros, however there's no responds_to? call on AST typenodes. There probably should be though
This should do it:
{% raise "Action not found" unless controller.resolve.methods.any? { |node| node.name == action.id } %}
@RX14 One would expect, the responds_to? to refer to a method available on the type node object ifself, not the type it describes. If there would be a short cut on Macros::Type is should rather be method? or similar.
TypeNode already has has_constant? and has_attribute?, so has_method? would probably be the ideal name.
Thanks @RX14 @straight-shoota, that works. It is really neat if we can have has_method? too.
@shulhi I've opened #4474 for this.
Most helpful comment
TypeNodealready hashas_constant?andhas_attribute?, sohas_method?would probably be the ideal name.