/
params.rb
181 lines (166 loc) · 4.46 KB
/
params.rb
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
require 'lotus/utils/attributes'
require 'lotus/validations'
require 'set'
module Lotus
module Action
# A set of params requested by the client
#
# It's able to extract the relevant params from a Rack env of from an Hash.
#
# There are three scenarios:
# * When used with Lotus::Router: it contains only the params from the request
# * When used standalone: it contains all the Rack env
# * Default: it returns the given hash as it is. It's useful for testing purposes.
#
# @since 0.1.0
class Params
# The key that returns raw input from the Rack env
#
# @since 0.1.0
RACK_INPUT = 'rack.input'.freeze
# The key that returns router params from the Rack env
# This is a builtin integration for Lotus::Router
#
# @since 0.1.0
ROUTER_PARAMS = 'router.params'.freeze
# Whitelist and validate a parameter
#
# @param name [#to_sym] The name of the param to whitelist
#
# @raise [ArgumentError] if one the validations is unknown, or if
# the size validator is used with an object that can't be coerced to
# integer.
#
# @return void
#
# @since 0.3.0
#
# @see http://rdoc.info/gems/lotus-validations/Lotus/Validations
#
# @example Whitelisting
# require 'lotus/controller'
#
# class SignupParams < Lotus::Action::Params
# param :email
# end
#
# params = SignupParams.new({id: 23, email: 'mjb@example.com'})
#
# params[:email] # => 'mjb@example.com'
# params[:id] # => nil
#
# @example Validation
# require 'lotus/controller'
#
# class SignupParams < Lotus::Action::Params
# param :email, presence: true
# end
#
# params = SignupParams.new({})
#
# params[:email] # => nil
# params.valid? # => false
#
# @example Unknown validation
# require 'lotus/controller'
#
# class SignupParams < Lotus::Action::Params
# param :email, unknown: true # => raise ArgumentError
# end
#
# @example Wrong size validation
# require 'lotus/controller'
#
# class SignupParams < Lotus::Action::Params
# param :email, size: 'twentythree'
# end
#
# params = SignupParams.new({})
# params.valid? # => raise ArgumentError
def self.param(name, options = {})
attribute name, options
nil
end
include Lotus::Validations
def self.whitelisting?
defined_attributes.any?
end
# @attr_reader env [Hash] the Rack env
#
# @since 0.2.0
# @api private
attr_reader :env
# Initialize the params and freeze them.
#
# @param env [Hash] a Rack env or an hash of params.
#
# @return [Params]
#
# @since 0.1.0
def initialize(env)
@env = env
_compute_params
# freeze
end
# Returns the object associated with the given key
#
# @param key [Symbol] the key
#
# @return [Object,nil] return the associated object, if found
#
# @since 0.2.0
def [](key)
@attributes.get(key)
end
# Returns the Ruby's hash
#
# @return [Hash]
#
# @since 0.3.0
def to_h
@attributes.to_h
end
alias_method :to_hash, :to_h
private
# Compatibility with Lotus::Validations
#
# @since 0.3.1
# @api private
def read_attributes
to_h
end
# @since 0.3.1
# @api private
def _compute_params
@attributes = if self.class.whitelisting?
_whitelisted_params
else
_params
end
@attributes = Utils::Attributes.new(@attributes)
end
# @since 0.3.1
# @api private
def _params
{}.tap do |result|
if env.has_key?(RACK_INPUT)
result.merge! ::Rack::Request.new(env).params
result.merge! env.fetch(ROUTER_PARAMS, {})
else
result.merge! env.fetch(ROUTER_PARAMS, env)
end
end
end
# @since 0.3.1
# @api private
def _whitelisted_params
{}.tap do |result|
_params.each do |k, v|
next unless self.class.defined_attributes.include?(k.to_s)
result[k] = v
end
end
end
end
end
end