/
define_attribute.cr
97 lines (79 loc) · 2.52 KB
/
define_attribute.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
module Avram::DefineAttribute
macro ensure_base_attributes_method_is_present
{% if !@type.methods.map(&.name).includes?(:attributes.id) %}
def attributes
[] of Avram::PermittedAttribute(Nil)
end
{% end %}
end
macro included
ATTRIBUTES = [] of Nil
macro inherited
inherit_attributes
end
end
macro inherit_attributes
\{% if !@type.constant(:ATTRIBUTES) %}
ATTRIBUTES = [] of Nil
\{% end %}
\{% if !@type.ancestors.first.abstract? %}
\{% for attribute in @type.ancestors.first.constant :ATTRIBUTES %}
\{% ATTRIBUTES << attribute %}
\{% end %}
\{% end %}
macro inherited
inherit_attributes
end
end
ensure_base_attributes_method_is_present
macro attribute(type_declaration)
{% if type_declaration.type.is_a?(Union) %}
{% if type_declaration.value.is_a?(Nop) %}
{% default_value = "" %}
{% else %}
{% default_value = "= #{type_declaration.value}" %}
{% end %}
{% raise <<-ERROR
`attribute` in #{@type} must not be called with a type union or nilable type but was called with #{type_declaration.type}
If you were attempting to create a nilable attribute, all attributes are considered nilable by default.
Try this...
attribute #{type_declaration.var} : #{type_declaration.type.types.first} #{default_value.id}
Read more on attributes: https://luckyframework.org/guides/database/validating-saving
ERROR
%}
{% end %}
{% ATTRIBUTES << type_declaration %}
{% type = type_declaration.type %}
{% name = type_declaration.var %}
{%
default_value = if type_declaration.value.is_a?(Nop)
nil
else
type_declaration.value
end
%}
@_{{ name }} : Avram::Attribute({{ type }})?
ensure_base_attributes_method_is_present
def attributes
([{{ name }}] + previous_def + super).uniq
end
def {{ name }}
_{{ name }}.permitted
end
private def _{{ name }}
@_{{ name }} ||= Avram::Attribute({{ type }}).new(
name: {{ name.id.symbolize }},
value: {{ default_value }},
param_key: self.class.param_key
).tap do |attribute|
attribute.extract(params)
end
end
end
macro file_attribute(key)
{% unless key.is_a?(SymbolLiteral) %}
{% raise "file_attribute must be declared with a Symbol" %}
{% end %}
attribute {{ key.id }} : Avram::Uploadable
end
end