-
Notifications
You must be signed in to change notification settings - Fork 2
/
parameter_bag.cr
112 lines (98 loc) · 3.61 KB
/
parameter_bag.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
# A container for storing key/value pairs. Can be used to store arbitrary data within the context of a request.
# It can be accessed via `ATH::Request#attributes`.
#
# ### Example
#
# For example, an artbirary value can be stored in the attributes, and later provided as an action argument.
#
# ```
# require "athena"
#
# # Define a request listener to add our value before the action is executed.
# @[ADI::Register]
# struct TestListener
# include AED::EventListenerInterface
#
# @[AEDA::AsEventListener]
# def on_request(event : ATH::Events::Request) : Nil
# # Store our value within the request's attributes, restricted to a `String`.
# event.request.attributes.set "my_arg", "foo", String
# end
# end
#
# class ExampleController < ATH::Controller
# # Define an action parameter with the same name of the parameter stored in attributes.
# #
# # The argument to pass is resolved via `ATHR::RequestAttribute`.
# get "/", my_arg : String do
# my_arg
# end
# end
#
# ATH.run
#
# # GET / # => "foo"
# ```
struct Athena::Framework::ParameterBag
private abstract struct Param
abstract def value
end
private record Parameter(T) < Param, value : T
@parameters : Hash(String, Param) = Hash(String, Param).new
# Returns `true` if a parameter with the provided *name* exists, otherwise `false`.
def has?(name : String) : Bool
@parameters.has_key? name
end
# Returns `true` if a parameter with the provided *name* exists and is of the provided *type*, otherwise `false`.
def has?(name : String, type : T.class) : Bool forall T
self.has?(name) && @parameters[name].value.class == T
end
# Returns the value of the parameter with the provided *name* if it exists, otherwise `nil`.
def get?(name : String)
@parameters[name]?.try &.value
end
# Returns the value of the parameter with the provided *name* casted to the provided *type* if it exists, otherwise `nil`.
def get?(name : String, type : T?.class) : T? forall T
self.get?(name).as? T?
end
# Returns the value of the parameter with the provided *name*.
#
# Raises a `KeyError` if no parameter with that name exists.
def get(name : String)
@parameters.fetch(name) { raise KeyError.new "No parameter exists with the name '#{name}'." }.value
end
# Returns the value of the parameter with the provided *name*, casted to the provided *type*.
#
# Raises a `KeyError` if no parameter with that name exists.
def get(name : String, type : T.class) : T forall T
self.get(name).as T
end
{% for type in [Bool, String] + Number::Primitive.union_types %}
# Returns the value of the parameter with the provided *name* as a `{{type}}`.
def get(name : String, _type : {{type}}.class) : {{type}}
{{type}}.from_parameter(self.get(name)).as {{type}}
end
# Returns the value of the parameter with the provided *name* as a `{{type}}`, or `nil` if it does not exist.
def get?(name : String, _type : {{type}}?.class) : {{type}}?
return nil unless (value = self.get? name)
{{type}}.from_parameter?(value).as? {{type}}?
end
{% end %}
def set(hash : Hash) : Nil
hash.each do |key, value|
self.set key, value
end
end
# Sets a parameter with the provided *name* to *value*.
def set(name : String, value : T) : Nil forall T
self.set name, value, T
end
# Sets a parameter with the provided *name* to *value*, restricted to the given *type*.
def set(name : String, value : T, type : T.class) : Nil forall T
@parameters[name] = Parameter(T).new value
end
# Removes the parameter with the provided *name*.
def remove(name : String) : Nil
@parameters.delete name
end
end