/
field.cr
112 lines (98 loc) · 3.41 KB
/
field.cr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
require "./field/base"
require "./field/big_int"
require "./field/bool"
require "./field/date"
require "./field/date_time"
require "./field/email"
require "./field/file"
require "./field/float"
require "./field/int"
require "./field/string"
require "./field/text"
require "./field/uuid"
require "./field/many_to_many"
require "./field/many_to_one"
require "./field/one_to_one"
module Marten
module DB
module Field
annotation Registration
end
@@registry = {} of ::String => Base.class
def self.registry
@@registry
end
macro register(id, field_klass)
{% klass = field_klass.resolve %}
{% defining_type_method_name = "from_db_result_set" %}
{% exposed_type = nil %}
{% method = klass.methods.find { |m| m.name == defining_type_method_name } %}
{% unless method %}
{% for ancestor_klass in klass.ancestors %}
{% method = ancestor_klass.methods.find { |m| m.name == defining_type_method_name } unless method %}
{% end %}
{% end %}
{% exposed_type = method.return_type %}
{% additional_type = nil %}
{% for method in klass.methods %}
{% if method.name == "from_db_result_set" %}
{% exposed_type = method.return_type %}
{% end %}
{% if klass.has_constant?(:AdditionalType) %}
{% additional_type = klass.constant(:AdditionalType) %}
{% end %}
{% end %}
{% unless exposed_type %}
{% for parent_klass in klass.ancestors %}
{% for method in parent_klass.methods %}
{% if !exposed_type && method.name == "from_db_result_set" %}
{% exposed_type = method.return_type %}
{% end %}
{% if !additional_type && parent_klass.has_constant?(:AdditionalType) %}
{% additional_type = parent_klass.constant(:AdditionalType) %}
{% end %}
{% end %}
{% end %}
{% end %}
@[Marten::DB::Field::Registration(
id: {{ id }},
exposed_type: {{ exposed_type }},
additional_type: {{ additional_type }}
)]
class ::{{klass.id}}; end
Marten::DB::Field.add_field_to_registry({{ id }}, {{ klass }})
end
# :nodoc:
def self.add_field_to_registry(id : ::String | Symbol, field_klass : Base.class)
@@registry[id.to_s] = field_klass
end
macro finished
{% field_types = [] of String %}
{% for k in Marten::DB::Field::Base.all_subclasses %}
{% ann = k.annotation(Marten::DB::Field::Registration) %}
{% if ann %}
{% field_types << ann[:exposed_type] %}
{% if ann[:additional_type] %}
{% field_types << ann[:additional_type] %}
{% end %}
{% end %}
{% end %}
alias Any = Symbol | {% for t, i in field_types %}{{ t }}{% if i + 1 < field_types.size %} | {% end %}{% end %}
end
register "big_int", BigInt
register "bool", Bool
register "date", Date
register "date_time", DateTime
register "email", Email
register "file", File
register "float", Float
register "int", Int
register "many_to_many", ManyToMany
register "many_to_one", ManyToOne
register "one_to_one", OneToOne
register "string", String
register "text", Text
register "uuid", UUID
end
end
end