luckyframework / lucky

A full-featured Crystal web framework that catches bugs for you, runs incredibly fast, and helps you write code that lasts.
https://luckyframework.org
MIT License
2.57k stars 156 forks source link

Custom param parser escape hatch #1845

Open jwoertink opened 7 months ago

jwoertink commented 7 months ago

I was thinking about how we could allow any custom type in params without needing to support everything. The best way is just provide an escape hatch so when you need something super custom, you have access to it.

For params, maybe you're doing a JSON API (or in my case, graphql), and you want to pass in a custom type

class Graph::Comments::Create < GraphAction
  param comment_input : Graph::Inputs::CommentInput

  post "/graph/comments/create_comment" do
    #....
  end
end

In this case, it's going to be some sort of nested JSON object. We could maybe use an annotation here to let you specify your own parser. Crystal's JSON::Serializable actually has a similar option where you can pass converter like the EpochConverter.

So I'm thinking maybe it looks something like

class Graph::Comments::Create < GraphAction

  # note: can't be Lucky::Param 
  @[Lucky::Param(converter: Graph::Inputs::CommentInput)]
  param comment_input : Graph::Inputs::CommentInput

  post "/graph/comments/create_comment" do
    #....
  end
end

class Graph::Inputs::CommentInput
  include JSON::Serializable

   property text : String
   property author_id : Int64

  # no clue how this would work, but maybe this is ok?
   def self.from_params(value : String)
      self.from_json(value)
   end
end

I'm sure there's a lot of weird edge cases around this, but I wanted to at least get this written down.