despecable 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 27abde4ea35465717dd657bc7243ecd69d5060a266531a444db7a1193ca5ba5d
4
- data.tar.gz: 85bac7c82642febacbbb55aa1dddbd7673ae5fc921741da3f9d49d8ac097424b
3
+ metadata.gz: 21d4ff25fc5caeb17ccfea449764dc172f51d7cf9e1bf0029a940fed5b0afae5
4
+ data.tar.gz: 84773247671c2b31f2a7c898aba845b69857d5c6af096f655bef45a58c738e55
5
5
  SHA512:
6
- metadata.gz: 2de10da5e0c3743cbb77e3bf3668f6e30015f05c7ca8d5d54c80715f16b24a8bbf3d27a6e7b39c53e691dadaf0c03770062e2bebf303fc194c2ac88be72e4556
7
- data.tar.gz: 060645f9d637a3028c3dee97ea8850444e2f4b88cb2e178a998955b0893bd77bc7010e2dda5a552d2f2e9e7c599cccfc8739f9b2d462979539cbb1330f61ff04
6
+ metadata.gz: 50acf3db2969b86d2328b72fdeaaf87bcff50694087376763e4761c49a86a84d9fa5dd971069085579afda5a45307241ed5e5ec0dc5f74c416b1f78e0a23b716
7
+ data.tar.gz: c57eb7a82041c66f64a08c669fc1e690098b456204c3a6119de8a5b19386595ab2a38d9f47275c106fae5021411c60dc1c861daa07a4ddcd783e4d5ee96ab3bf
@@ -1,24 +1,29 @@
1
1
  module Despecable
2
2
  module ActionController
3
3
  def despec(*args, strict: false, &blk)
4
- despecable_me(params.dup).doit(*args, strict: strict, &blk)
4
+ output_params = params.dup
5
+ parsed = despecable_me(output_params).doit(*args, &blk)
6
+ despecable_me.strict(request.query_parameters.keys + request.request_parameters.keys) if strict
7
+ parsed.each do |key, val|
8
+ output_params[key] = val
9
+ end
10
+ return output_params
5
11
  end
6
12
 
7
- def despec!(*args, &blk)
8
- despec(*args, &blk)
9
- # Loop in place of merge due to unpermitted params restriction
10
- despecable_me.params.each do |key, val|
13
+ def despec!(*args, strict: false, &blk)
14
+ parsed = despecable_me(params).doit(*args, &blk)
15
+ despecable_me.strict(request.query_parameters.keys + request.request_parameters.keys) if strict
16
+ parsed.each do |key, val|
11
17
  params[key] = val
12
18
  end
19
+ return params
13
20
  end
14
21
 
22
+ # A cached instance of Despecable::Me will keep track of all despec calls
23
+ # in a given request / action. This allows despec to be called multiple
24
+ # times (e.g. in before_actions) and keep track of all spec'd params
15
25
  def despecable_me(params = {})
16
- supplied_params = request.query_parameters.dup
17
- # Loop in place of merge due to unpermitted params restriction
18
- request.request_parameters.each do |key, val|
19
- supplied_params[key] = val
20
- end
21
- @despecable_me ||= Despecable::Me.new(params, supplied_params)
26
+ @despecable_me ||= Despecable::Me.new(params)
22
27
  end
23
28
  end
24
29
  end
@@ -2,33 +2,26 @@ module Despecable
2
2
  class Me
3
3
  attr_reader :params
4
4
 
5
- # supplied_params are the params that were actually passed in by the user.
6
- # In Rails, params has some additional keys (e.g. controller, action), so you can
7
- # pass in request.query_parameters (GET) and/or request.request_parameters (POST)
8
- # for supplied_params to correctly get only the user-supplied parameters.
9
- def initialize(params, supplied_params = nil)
10
- @supplied_params = (supplied_params || params).dup
5
+ def initialize(params)
11
6
  @params = params
12
7
  @specd = []
13
8
  end
14
9
 
15
- def doit(*args, strict: false, &blk)
10
+ def doit(*args, &blk)
16
11
  spectator = Despecable::Spectator.new(@params)
17
12
  spectator.instance_exec(*args, &blk) unless blk.nil?
18
13
  @specd += spectator.specd
19
- despecably_strict if strict
20
14
  return spectator.params
21
15
  end
22
16
 
23
- def unspecd
24
- @supplied_params.keys.map(&:to_s) - @specd.map(&:to_s)
25
- end
26
-
27
- def despecably_strict
17
+ def strict(user_params)
18
+ unspecd = user_params.map(&:to_s).uniq - @specd.map(&:to_s)
28
19
  if !unspecd.empty?
29
20
  list = unspecd.map{|x| "'#{x}'"}.join(", ")
30
- error = Despecable::UnrecognizedParameterError.new("Unrecognized parameters supplied: #{list}", parameters: unspecd)
31
- raise error
21
+ raise Despecable::UnrecognizedParameterError.new(
22
+ "Unrecognized parameters supplied: #{list}",
23
+ parameters: unspecd
24
+ )
32
25
  end
33
26
  end
34
27
  end
@@ -1,5 +1,16 @@
1
1
  module Despecable
2
2
  class Spectacles
3
+ def read(name, value, type, options, &blk)
4
+ if options[:array]
5
+ arrayify(value).map{|val| parse(name, val, type, options, &blk)}
6
+ elsif options[:arrayable] && arrayable?(value)
7
+ # TODO: :arrayable is deprecated in favor of :array
8
+ arrayify(value).map{|val| parse(name, val, type, options, &blk)}
9
+ else
10
+ parse(name, value, type, options, &blk)
11
+ end
12
+ end
13
+
3
14
  def arrayable?(value)
4
15
  value.is_a?(::Array) || /,/ =~ value.to_s
5
16
  end
@@ -9,19 +20,10 @@ module Despecable
9
20
  value.to_s.split(",")
10
21
  end
11
22
 
12
- def read(name, value, type, options)
13
- value = public_send(type, name, value, options) unless value.nil?
14
- validate_param(name, value, options)
15
- return value
16
- end
17
-
18
- def validate_param(name, value, options)
19
- validate_param_presence(name, value) if options[:required]
23
+ def parse(name, value, type, options, &blk)
24
+ value = public_send(type, name, value, options, &blk)
20
25
  validate_param_value(name, value, options) if options.key?(:in) && !value.nil?
21
- end
22
-
23
- def validate_param_presence(name, value)
24
- raise Despecable::MissingParameterError.new("Missing required parameter: '#{name}'", parameters: name) if value.nil?
26
+ return value
25
27
  end
26
28
 
27
29
  def validate_param_value(name, value, options)
@@ -110,5 +112,9 @@ module Despecable
110
112
  def any(name, value, options)
111
113
  value
112
114
  end
115
+
116
+ def custom(name, value, options)
117
+ return yield(name, value, options)
118
+ end
113
119
  end
114
120
  end
@@ -1,9 +1,15 @@
1
1
  module Despecable
2
2
  class Spectator < BasicObject
3
+ # This class is used to read (eval) the despec block
4
+ # Any methods in that block must be defined here, and this object
5
+ # must be stateful to be read by the controller
6
+
3
7
  attr_reader :params, :specd
4
8
 
5
9
  def initialize(params)
6
- @params = params
10
+ @input_params = params
11
+ # TODO: allow this to be the same object to save copies
12
+ @params = {}
7
13
  @spectacles = ::Despecable::Spectacles.new
8
14
  @specd = []
9
15
  end
@@ -40,22 +46,20 @@ module Despecable
40
46
  _spec(name, :any, options)
41
47
  end
42
48
 
49
+ def custom(name, options = {}, &blk)
50
+ _spec(name, :custom, options, &blk)
51
+ end
52
+
43
53
  private
44
54
 
45
- def _spec(name, type, options = {})
55
+ def _spec(name, type, options = {}, &blk)
46
56
  @specd << (name)
47
- if !params.key?(name) && options.key?(:default)
48
- params[name] = options[:default]
49
- elsif options[:array]
50
- values = @spectacles.arrayify(params[name])
51
- params[name] = values.map{|val| @spectacles.read(name, val, type, options)}
52
- elsif options[:arrayable] && @spectacles.arrayable?(params[name])
53
- # TODO: deprecate arrayable in favor of array
54
- values = @spectacles.arrayify(params[name])
55
- params[name] = values.map{|val| @spectacles.read(name, val, type, options)}
56
- else
57
- value = @spectacles.read(name, params[name], type, options)
58
- params[name] = value if params.key?(name)
57
+ if @input_params.key?(name)
58
+ @params[name] = @spectacles.read(name, @input_params[name], type, options, &blk)
59
+ elsif options.key?(:default)
60
+ @params[name] = options[:default]
61
+ elsif options.key?(:required)
62
+ ::Kernel.raise ::Despecable::MissingParameterError.new("Missing required parameter: '#{name}'", parameters: name)
59
63
  end
60
64
  end
61
65
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: despecable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Schwartz