I want to know if i'm using correctly the splats with named arguments for macros.
require "http/server"
abstract class Filter
def call(context : HTTP::Context)
end
end
macro get(*routes, before, after = ([] of Filter | Filter | Nil), &block : -> T)
pp "test"
end
get "/v2/security/users/", param_test : String do |ctx|
pp "hello"
end
# get "/v2/security/users/", param_test : String, before: nil, after: nil do |ctx|
# pp "hello"
# end
I'm working on an experimental web framework. The code in the comments works ok but the uncommented one throws this error:
declaring the type of a local variable is not yet supported
_get "/v2/security/users/", param_test : String do |ctx|_
It's definitely inconsistent, however I'm afraid my argument will go into the opposite direction than what you would like to see.
I would say both cases should error, given that declaring the type of a local variable is not yet valid, so shouldn't doing it be syntactically anywhere. Neither variant should produce a valid AST node for param_test : String at any point, both should give a syntax error.
@jhass, it's nice to see that point of view, this way i don't lose my time with the new web framework.
I'll love to have this kind of syntax for autoloading entities from databases based on the TypeDeclaration and adding the name of the variable to the http context so it could be used in the block.
require "http/server"
class User
property id
def initialize(param : RouteParam)
@id = param
pp "load param with the id: #{param}"
end
end
abstract class Filter
def call(context : HTTP::Context)
end
end
macro get(*routes, before, after = ([] of Filter | Filter | Nil), &block : -> T)
#TODO: Autoloading of route and params
end
get "/v2/security/user/", user : User, "/edit" do |ctx|
pp ctx.user.id
end
Thanks for the feedback.
Take note that it's just my opinion, it's not decided yet. Also take note that both should work when declaring the type of locals will actually be possible (do we have an issue to track this we can link back to here?).
To offer an alternative, parsing named tuple literals like JSON.mapping etc. do should be even easier and well supported.
Not a bug:
macro get(*routes, before, after = ([] of Filter | Filter | Nil), &block : -> T)
pp "test"
end
get "/v2/security/users/", param_test : String do |ctx|
pp "hello"
end
The get macro expects a required before argument that you are not passing. So, get doesn't match that macro and is tried to be executed as a method call. For method calls we first type its arguments, and then you get an error about param_test.
This works:
macro get(*routes, before = nil, after = ([] of Filter | Filter | Nil), &block : -> T)
pp "test"
end
get "/v2/security/users/", param_test : String do |ctx|
pp "hello"
end
Side note: not sure what you mean with [] of Filter | Filter | Nil, that's basically [] of Filter | Nil.
@asterite, thanks for the clarification, confirmed as not a bug. I use [] of Filter | Filter | Nil because i want be able to do this:
get "/v2/security/users/", param_test : String, before: AuthenticationFilter, after: [FormatFilter, PoolDetachFilter] do |ctx|
pp "hello"
end
But [] of Filter | Filter | Nil is parsed as [] of (Filter | Filter | Nil). Plus, it doesn't make much sense as a default value (it makes sense as a type restriction).
My bad, i'm still learning developing with macros and type restrictions. I'll move the type restriction to the routes loader generated functions. Thanks for all your help.
Everyday i'm loving more to work with crystal and experimenting all the new features.