-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathsr_elements.erl
138 lines (118 loc) · 3.61 KB
/
sr_elements.erl
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
%%% @doc Elements Model
-module(sr_elements).
-behaviour(sumo_doc).
-behaviour(sumo_rest_doc).
-type key() :: integer().
-type value() :: binary() | iodata().
-opaque element() ::
#{ key => key()
, value => value()
, created_at => calendar:datetime()
, updated_at => calendar:datetime()
}.
-export_type(
[ element/0
, key/0
, value/0
]).
-export(
[ sumo_schema/0
, sumo_wakeup/1
, sumo_sleep/1
]).
-export(
[ new/2
, key/1
, value/1
, updated_at/1
]).
-export(
[ to_json/1
, from_json/1
, location/2
, duplication_conditions/1
, update/2
, id_from_binding/1
]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% BEHAVIOUR CALLBACKS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-spec sumo_schema() -> sumo:schema().
sumo_schema() ->
sumo:new_schema(elements,
[ sumo:new_field(key, integer, [id, not_null])
, sumo:new_field(value, string, [not_null])
, sumo:new_field(created_at, datetime, [not_null])
, sumo:new_field(updated_at, datetime, [not_null])
]).
-spec sumo_sleep(element()) -> sumo:model().
sumo_sleep(Element) -> Element.
-spec sumo_wakeup(sumo:model()) -> element().
sumo_wakeup(Element) -> Element.
-spec to_json(element()) -> sr_json:json().
to_json(Element) ->
#{ key => maps:get(key, Element)
, value => maps:get(value, Element)
, created_at => sr_json:encode_date(maps:get(created_at, Element))
, updated_at => sr_json:encode_date(maps:get(updated_at, Element))
}.
-spec from_json(sumo_rest_doc:json()) -> {ok, element()} | {error, iodata()}.
from_json(Json) ->
Now = sr_json:encode_date(calendar:universal_time()),
try
{ ok
, #{ key => maps:get(<<"key">>, Json)
, value => maps:get(<<"value">>, Json)
, created_at =>
sr_json:decode_date(maps:get(<<"created_at">>, Json, Now))
, updated_at =>
sr_json:decode_date(maps:get(<<"updated_at">>, Json, Now))
}
}
catch
_:{badkey, Key} ->
{error, <<"missing field: ", Key/binary>>}
end.
-spec update(element(), sumo_rest_doc:json()) ->
{ok, element()} | {error, iodata()}.
update(Element, Json) ->
try
NewValue = maps:get(<<"value">>, Json),
UpdatedElement =
Element#{value := NewValue, updated_at := calendar:universal_time()},
{ok, UpdatedElement}
catch
_:{badkey, Key} ->
{error, <<"missing field: ", Key/binary>>}
end.
-spec location(element(), sumo_rest_doc:path()) -> binary().
location(Element, Path) -> iolist_to_binary([Path, "/", key(Element)]).
-spec duplication_conditions(element()) ->
sumo_rest_doc:duplication_conditions().
duplication_conditions(Element) -> [{key, '==', key(Element)}].
%% this function is implemented for testing purposes. If your key is integer,
%% binary or string this function is not needed.
-spec id_from_binding(binary()) -> key().
id_from_binding(BinaryId) ->
try binary_to_integer(BinaryId) of
Id -> Id
catch
error:badarg -> -1
end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% PUBLIC API
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-spec new(key(), value()) -> element().
new(Key, Value) ->
Now = calendar:universal_time(),
#{ key => Key
, value => Value
, created_at => Now
, updated_at => Now
}.
-spec key(element()) -> key().
key(#{key := Key}) -> Key.
-spec value(element()) -> value().
value(#{value := Value}) -> Value.
-spec updated_at(element()) -> calendar:datetime().
updated_at(#{updated_at := UpdatedAt}) -> UpdatedAt.