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`
Just an idea.