Crystal: Throwing exception when expanding macro?

Created on 27 May 2017  路  5Comments  路  Source: crystal-lang/crystal

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

Most helpful comment

TypeNode already has has_constant? and has_attribute?, so has_method? would probably be the ideal name.

All 5 comments

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

https://carc.in/#/r/238y

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

grosser picture grosser  路  3Comments

lbguilherme picture lbguilherme  路  3Comments

oprypin picture oprypin  路  3Comments

relonger picture relonger  路  3Comments

pbrusco picture pbrusco  路  3Comments