onyxframework / sql

A delightful SQL ORM ☺️
https://api.onyxframework.com/sql
MIT License
91 stars 7 forks source link

Restrict method arguments by model getters #99

Open vladfaust opened 5 years ago

vladfaust commented 5 years ago

Just an idea.

module Onyx::SQL
  macro restrict(t, model, &block)
    {% for exp in block.body.expressions %}
      {% unless exp.is_a?(Call) && exp.name == "getter" %}
        {% raise "Must be getter" %}
      {% end %}

      {% found = false %}

      {% for method in t.methods %}
        {% if method.name == exp.args.first.var &&
                method.return_type == exp.args.first.type %}
          {% found = true %}
        {% end %}
      {% end %}

      {% raise "#{model} is restricted to have `#{exp.args.first.var}` getter with return type `#{exp.args.first.type}`" unless found %}
    {% end %}
  end
end

class User
  property id : Int32?
  property name : String?

  def initialize(@id = nil, @name = nil)
  end
end

def foo(user : T) forall T
  Onyx::SQL.restrict({{T}}, User) do
    getter id : Int32
    getter name : String?
  end

  pp user
end

record UserObject, id : Int32, name : String?

# foo(UserObject.new(42, nil)) # OK
foo(User.new(42, nil)) # User is restricted to have `id` getter with return type `Int32`