haveapi 0.20.0 → 0.21.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.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Rakefile +6 -6
  4. data/haveapi.gemspec +13 -13
  5. data/lib/haveapi/action.rb +153 -167
  6. data/lib/haveapi/action_state.rb +2 -6
  7. data/lib/haveapi/actions/default.rb +8 -10
  8. data/lib/haveapi/api.rb +2 -1
  9. data/lib/haveapi/authentication/base.rb +5 -8
  10. data/lib/haveapi/authentication/basic/provider.rb +4 -5
  11. data/lib/haveapi/authentication/chain.rb +19 -17
  12. data/lib/haveapi/authentication/oauth2/config.rb +12 -32
  13. data/lib/haveapi/authentication/oauth2/provider.rb +20 -30
  14. data/lib/haveapi/authentication/oauth2/revoke_endpoint.rb +1 -2
  15. data/lib/haveapi/authentication/token/action_config.rb +5 -3
  16. data/lib/haveapi/authentication/token/config.rb +5 -5
  17. data/lib/haveapi/authentication/token/provider.rb +33 -37
  18. data/lib/haveapi/authorization.rb +10 -4
  19. data/lib/haveapi/client_example.rb +11 -14
  20. data/lib/haveapi/client_examples/curl.rb +37 -37
  21. data/lib/haveapi/client_examples/fs_client.rb +29 -31
  22. data/lib/haveapi/client_examples/http.rb +35 -36
  23. data/lib/haveapi/client_examples/js_client.rb +62 -63
  24. data/lib/haveapi/client_examples/php_client.rb +77 -76
  25. data/lib/haveapi/client_examples/ruby_cli.rb +30 -30
  26. data/lib/haveapi/client_examples/ruby_client.rb +26 -26
  27. data/lib/haveapi/common.rb +3 -4
  28. data/lib/haveapi/context.rb +11 -10
  29. data/lib/haveapi/example.rb +9 -4
  30. data/lib/haveapi/example_list.rb +2 -2
  31. data/lib/haveapi/exceptions.rb +1 -1
  32. data/lib/haveapi/extensions/action_exceptions.rb +2 -2
  33. data/lib/haveapi/extensions/base.rb +1 -3
  34. data/lib/haveapi/extensions/exception_mailer.rb +260 -257
  35. data/lib/haveapi/hooks.rb +40 -39
  36. data/lib/haveapi/metadata.rb +1 -1
  37. data/lib/haveapi/model_adapter.rb +16 -27
  38. data/lib/haveapi/model_adapters/active_record.rb +59 -69
  39. data/lib/haveapi/output_formatter.rb +7 -7
  40. data/lib/haveapi/output_formatters/base.rb +2 -4
  41. data/lib/haveapi/parameters/resource.rb +7 -7
  42. data/lib/haveapi/parameters/typed.rb +6 -9
  43. data/lib/haveapi/params.rb +38 -45
  44. data/lib/haveapi/resource.rb +8 -8
  45. data/lib/haveapi/resources/action_state.rb +11 -19
  46. data/lib/haveapi/server.rb +102 -107
  47. data/lib/haveapi/spec/api_response.rb +1 -1
  48. data/lib/haveapi/spec/helpers.rb +1 -1
  49. data/lib/haveapi/spec/mock_action.rb +11 -10
  50. data/lib/haveapi/spec/spec_methods.rb +9 -8
  51. data/lib/haveapi/tasks/yard.rb +2 -2
  52. data/lib/haveapi/types.rb +0 -3
  53. data/lib/haveapi/validator.rb +6 -3
  54. data/lib/haveapi/validator_chain.rb +9 -8
  55. data/lib/haveapi/validators/acceptance.rb +6 -6
  56. data/lib/haveapi/validators/confirmation.rb +2 -3
  57. data/lib/haveapi/validators/exclusion.rb +1 -1
  58. data/lib/haveapi/validators/format.rb +1 -1
  59. data/lib/haveapi/validators/inclusion.rb +1 -1
  60. data/lib/haveapi/validators/length.rb +12 -11
  61. data/lib/haveapi/validators/numericality.rb +14 -13
  62. data/lib/haveapi/validators/presence.rb +4 -3
  63. data/lib/haveapi/version.rb +2 -2
  64. data/lib/haveapi.rb +2 -3
  65. data/spec/.rubocop.yml +4 -0
  66. data/spec/action/dsl_spec.rb +18 -18
  67. data/spec/authorization_spec.rb +8 -8
  68. data/spec/common_spec.rb +2 -1
  69. data/spec/documentation_spec.rb +2 -9
  70. data/spec/envelope_spec.rb +2 -2
  71. data/spec/hooks_spec.rb +12 -12
  72. data/spec/parameters/typed_spec.rb +6 -6
  73. data/spec/params_spec.rb +22 -24
  74. data/spec/resource_spec.rb +5 -7
  75. data/spec/spec_helper.rb +0 -1
  76. data/spec/validators/acceptance_spec.rb +1 -1
  77. data/spec/validators/confirmation_spec.rb +5 -5
  78. data/spec/validators/exclusion_spec.rb +3 -3
  79. data/spec/validators/format_spec.rb +2 -2
  80. data/spec/validators/inclusion_spec.rb +4 -4
  81. data/spec/validators/length_spec.rb +23 -23
  82. data/spec/validators/numericality_spec.rb +13 -13
  83. data/spec/validators/presence_spec.rb +3 -3
  84. metadata +49 -48
@@ -29,7 +29,7 @@ module HaveAPI
29
29
  def describe
30
30
  {
31
31
  values: @values,
32
- message: @message,
32
+ message: @message
33
33
  }
34
34
  end
35
35
 
@@ -28,7 +28,7 @@ module HaveAPI
28
28
  rx: @rx.source,
29
29
  match: @match,
30
30
  description: @desc,
31
- message: @message,
31
+ message: @message
32
32
  }
33
33
  end
34
34
 
@@ -37,7 +37,7 @@ module HaveAPI
37
37
  def describe
38
38
  {
39
39
  values: @values,
40
- message: @message,
40
+ message: @message
41
41
  }
42
42
  end
43
43
 
@@ -23,31 +23,31 @@ module HaveAPI
23
23
  @equals = take(:equals)
24
24
 
25
25
  if (@min || @max) && @equals
26
- fail 'cannot mix min/max with equals'
26
+ raise 'cannot mix min/max with equals'
27
27
 
28
28
  elsif !@min && !@max && !@equals
29
- fail 'must use either min, max or equals'
29
+ raise 'must use either min, max or equals'
30
30
  end
31
31
 
32
32
  msg = if @equals
33
- "length has to be #{@equals}"
33
+ "length has to be #{@equals}"
34
34
 
35
- elsif @min && !@max
36
- "length has to be minimally #{@min}"
35
+ elsif @min && !@max
36
+ "length has to be minimally #{@min}"
37
37
 
38
- elsif !@min && @max
39
- "length has to be maximally #{@max}"
38
+ elsif !@min && @max
39
+ "length has to be maximally #{@max}"
40
40
 
41
- else
42
- "length has to be in range <#{@min}, #{@max}>"
43
- end
41
+ else
42
+ "length has to be in range <#{@min}, #{@max}>"
43
+ end
44
44
 
45
45
  @message = take(:message, msg)
46
46
  end
47
47
 
48
48
  def describe
49
49
  ret = {
50
- message: @message,
50
+ message: @message
51
51
  }
52
52
 
53
53
  if @equals
@@ -67,6 +67,7 @@ module HaveAPI
67
67
  return len == @equals if @equals
68
68
  return len >= @min if @min && !@max
69
69
  return len <= @max if !@min && @max
70
+
70
71
  len >= @min && len <= @max
71
72
  end
72
73
  end
@@ -33,17 +33,17 @@ module HaveAPI
33
33
  @odd = take(:odd)
34
34
 
35
35
  msg = if @min && !@max
36
- "has to be minimally #{@min}"
36
+ "has to be minimally #{@min}"
37
37
 
38
- elsif !@min && @max
39
- "has to be maximally #{@max}"
38
+ elsif !@min && @max
39
+ "has to be maximally #{@max}"
40
40
 
41
- elsif @min && @max
42
- "has to be in range <#{@min}, #{@max}>"
41
+ elsif @min && @max
42
+ "has to be in range <#{@min}, #{@max}>"
43
43
 
44
- else
45
- 'has to be a number'
46
- end
44
+ else
45
+ 'has to be a number'
46
+ end
47
47
 
48
48
  if @step
49
49
  msg += '; ' unless msg.empty?
@@ -57,16 +57,16 @@ module HaveAPI
57
57
 
58
58
  if @odd
59
59
  msg += '; ' unless msg.empty?
60
- msg += "odd"
60
+ msg += 'odd'
61
61
  end
62
62
 
63
63
  if @even
64
64
  msg += '; ' unless msg.empty?
65
- msg += "even"
65
+ msg += 'even'
66
66
  end
67
67
 
68
68
  if @odd && @even
69
- fail 'cannot be both odd and even at the same time'
69
+ raise 'cannot be both odd and even at the same time'
70
70
  end
71
71
 
72
72
  @message = take(:message, msg)
@@ -74,7 +74,7 @@ module HaveAPI
74
74
 
75
75
  def describe
76
76
  ret = {
77
- message: @message,
77
+ message: @message
78
78
  }
79
79
 
80
80
  ret[:min] = @min if @min
@@ -90,6 +90,7 @@ module HaveAPI
90
90
  def valid?(v)
91
91
  if v.is_a?(::String)
92
92
  return false if /\A\d+\z/ !~ v
93
+
93
94
  v = v.to_i
94
95
  end
95
96
 
@@ -98,7 +99,7 @@ module HaveAPI
98
99
  ret = false if @max && v > @max
99
100
  ret = false if @step && (v - (@min || 0)) % @step != 0
100
101
  ret = false if @mod && v % @mod != 0
101
- ret = false if @odd && v % 2 == 0
102
+ ret = false if @odd && v.even?
102
103
  ret = false if @even && v % 2 > 0
103
104
  ret
104
105
  end
@@ -20,21 +20,22 @@ module HaveAPI
20
20
 
21
21
  @empty = take(:empty, false)
22
22
  @message = take(
23
- :message,
24
- @empty ? 'must be present' : 'must be present and non-empty'
23
+ :message,
24
+ @empty ? 'must be present' : 'must be present and non-empty'
25
25
  )
26
26
  end
27
27
 
28
28
  def describe
29
29
  {
30
30
  empty: @empty,
31
- message: @message,
31
+ message: @message
32
32
  }
33
33
  end
34
34
 
35
35
  def valid?(v)
36
36
  return false if v.nil?
37
37
  return !v.strip.empty? if !@empty && v.is_a?(::String)
38
+
38
39
  # FIXME: other data types?
39
40
  true
40
41
  end
@@ -1,4 +1,4 @@
1
1
  module HaveAPI
2
- PROTOCOL_VERSION = '2.0'
3
- VERSION = '0.20.0'
2
+ PROTOCOL_VERSION = '2.0'.freeze
3
+ VERSION = '0.21.1'.freeze
4
4
  end
data/lib/haveapi.rb CHANGED
@@ -6,13 +6,12 @@ require 'active_record' if ar
6
6
  require 'sinatra/base'
7
7
  require 'sinatra/cookies'
8
8
  require 'sinatra/activerecord' if ar
9
- require 'pp'
10
9
  require 'github/markdown'
11
10
  require 'json'
12
11
 
13
12
  module HaveAPI
14
- module Resources ; end
15
- module Actions ; end
13
+ module Resources; end
14
+ module Actions; end
16
15
  end
17
16
 
18
17
  require_relative 'haveapi/params'
data/spec/.rubocop.yml ADDED
@@ -0,0 +1,4 @@
1
+ inherit_from: ../../../.rubocop.yml
2
+
3
+ Lint/ConstantDefinitionInBlock:
4
+ Enabled: false
@@ -8,7 +8,7 @@ describe HaveAPI::Action do
8
8
  end
9
9
  end
10
10
 
11
- class SubInputAction < InputAction ; end
11
+ class SubInputAction < InputAction; end
12
12
  end
13
13
 
14
14
  # Invokes execution of input/output blocks
@@ -24,9 +24,9 @@ describe HaveAPI::Action do
24
24
  end
25
25
  end
26
26
 
27
- class SubOutputAction < OutputAction ; end
27
+ class SubOutputAction < OutputAction; end
28
28
  end
29
-
29
+
30
30
  # Invokes execution of input/output blocks
31
31
  Resource.routes
32
32
  expect(Resource::SubOutputAction.output.params.first.name).to eq(:param)
@@ -44,11 +44,11 @@ describe HaveAPI::Action do
44
44
  end
45
45
  end
46
46
  end
47
-
47
+
48
48
  # Invokes execution of input/output blocks
49
49
  Resource.routes
50
50
 
51
- params = Resource::InputChainAction.input.params.map { |p| p.name }
51
+ params = Resource::InputChainAction.input.params.map(&:name)
52
52
  expect(params).to contain_exactly(:param1, :param2)
53
53
  end
54
54
 
@@ -64,11 +64,11 @@ describe HaveAPI::Action do
64
64
  end
65
65
  end
66
66
  end
67
-
67
+
68
68
  # Invokes execution of input/output blocks
69
69
  Resource.routes
70
70
 
71
- params = Resource::OutputChainAction.output.params.map { |p| p.name }
71
+ params = Resource::OutputChainAction.output.params.map(&:name)
72
72
  expect(params).to contain_exactly(:param1, :param2)
73
73
  end
74
74
 
@@ -116,16 +116,16 @@ describe HaveAPI::Action do
116
116
  # Invokes execution of input/output blocks
117
117
  Resource.routes
118
118
 
119
- input = Resource::SubAction.input.params.map { |p| p.name }
120
- output = Resource::SubAction.output.params.map { |p| p.name }
119
+ input = Resource::SubAction.input.params.map(&:name)
120
+ output = Resource::SubAction.output.params.map(&:name)
121
121
 
122
- expect(input).to contain_exactly(*%i(inbase1 inbase2 insub1 insub2 insub3))
123
- expect(output).to contain_exactly(*%i(outbase1 outbase2 outsub1 outsub2 outsub3))
122
+ expect(input).to contain_exactly(*%i[inbase1 inbase2 insub1 insub2 insub3])
123
+ expect(output).to contain_exactly(*%i[outbase1 outbase2 outsub1 outsub2 outsub3])
124
124
  end
125
125
 
126
126
  it 'sets layout' do
127
127
  class Resource < HaveAPI::Resource
128
- class DefaultLayoutAction < HaveAPI::Action ; end
128
+ class DefaultLayoutAction < HaveAPI::Action; end
129
129
 
130
130
  class ObjectLayoutAction < HaveAPI::Action
131
131
  input(:object) {}
@@ -136,17 +136,17 @@ describe HaveAPI::Action do
136
136
  input(:object_list) {}
137
137
  output(:object_list) {}
138
138
  end
139
-
139
+
140
140
  class HashLayoutAction < HaveAPI::Action
141
141
  input(:hash) {}
142
142
  output(:hash) {}
143
143
  end
144
-
144
+
145
145
  class HashListLayoutAction < HaveAPI::Action
146
146
  input(:hash_list) {}
147
147
  output(:hash_list) {}
148
148
  end
149
-
149
+
150
150
  class CombinedLayoutAction < HaveAPI::Action
151
151
  input(:hash) {}
152
152
  output(:object_list) {}
@@ -176,19 +176,19 @@ describe HaveAPI::Action do
176
176
  class ExResourceIn < HaveAPI::Resource
177
177
  class ExInputAction < HaveAPI::Action
178
178
  input do
179
- fail 'this is terrible!'
179
+ raise 'this is terrible!'
180
180
  end
181
181
  end
182
182
  end
183
183
 
184
184
  expect { ExResourceIn.routes }.to raise_error(HaveAPI::BuildError)
185
185
  end
186
-
186
+
187
187
  it 'catches exceptions in output' do
188
188
  class ExResourceOut < HaveAPI::Resource
189
189
  class ExOutputAction < HaveAPI::Action
190
190
  output do
191
- fail 'this is terrible!'
191
+ raise 'this is terrible!'
192
192
  end
193
193
  end
194
194
  end
@@ -37,7 +37,7 @@ describe HaveAPI::Authorization do
37
37
 
38
38
  it 'whitelists input' do
39
39
  auth = HaveAPI::Authorization.new do
40
- input whitelist: %i(param1)
40
+ input whitelist: %i[param1]
41
41
  allow
42
42
  end
43
43
 
@@ -49,14 +49,14 @@ describe HaveAPI::Authorization do
49
49
  action.input.params,
50
50
  action.model_adapter(action.input.layout).input({
51
51
  param1: '123',
52
- param2: '456',
52
+ param2: '456'
53
53
  })
54
54
  ).keys).to contain_exactly(:param1)
55
55
  end
56
56
 
57
57
  it 'blacklists input' do
58
58
  auth = HaveAPI::Authorization.new do
59
- input blacklist: %i(param1)
59
+ input blacklist: %i[param1]
60
60
  allow
61
61
  end
62
62
 
@@ -68,14 +68,14 @@ describe HaveAPI::Authorization do
68
68
  action.input.params,
69
69
  action.model_adapter(action.input.layout).input({
70
70
  param1: '123',
71
- param2: '456',
71
+ param2: '456'
72
72
  })
73
73
  ).keys).to contain_exactly(:param2)
74
74
  end
75
75
 
76
76
  it 'whitelists output' do
77
77
  auth = HaveAPI::Authorization.new do
78
- output whitelist: %i(param1)
78
+ output whitelist: %i[param1]
79
79
  allow
80
80
  end
81
81
 
@@ -87,14 +87,14 @@ describe HaveAPI::Authorization do
87
87
  action.output.params,
88
88
  action.model_adapter(action.output.layout).output(nil, {
89
89
  param1: '123',
90
- param2: '456',
90
+ param2: '456'
91
91
  })
92
92
  ).keys).to contain_exactly(:param1)
93
93
  end
94
94
 
95
95
  it 'blacklists output' do
96
96
  auth = HaveAPI::Authorization.new do
97
- output blacklist: %i(param1)
97
+ output blacklist: %i[param1]
98
98
  allow
99
99
  end
100
100
 
@@ -106,7 +106,7 @@ describe HaveAPI::Authorization do
106
106
  action.output.params,
107
107
  action.model_adapter(action.output.layout).output(nil, {
108
108
  param1: '123',
109
- param2: '456',
109
+ param2: '456'
110
110
  })
111
111
  ).keys).to contain_exactly(:param2)
112
112
  end
data/spec/common_spec.rb CHANGED
@@ -8,7 +8,7 @@ describe HaveAPI::Common do
8
8
  expect(Test1.attr1).to be_nil
9
9
  expect(Test1.attr2).to eq(42)
10
10
  end
11
-
11
+
12
12
  class Test2 < HaveAPI::Common
13
13
  has_attr :attr1
14
14
  has_attr :attr2, 42
@@ -31,6 +31,7 @@ describe HaveAPI::Common do
31
31
  attr2 :bar
32
32
 
33
33
  def self.inherited(subclass)
34
+ super
34
35
  inherit_attrs(subclass)
35
36
  end
36
37
  end
@@ -1,29 +1,22 @@
1
1
  describe 'Documentation' do
2
2
  it 'responds to OPTIONS /' do
3
-
4
3
  end
5
-
6
- it 'responds to OPTIONS /?describe=versions' do
7
4
 
5
+ it 'responds to OPTIONS /?describe=versions' do
8
6
  end
9
-
10
- it 'responds to OPTIONS /?describe=default' do
11
7
 
8
+ it 'responds to OPTIONS /?describe=default' do
12
9
  end
13
10
 
14
11
  it 'responds to OPTIONS /<version>' do
15
-
16
12
  end
17
13
 
18
14
  it 'responds to OPTIONS /<every action>?method=<method>' do
19
-
20
15
  end
21
16
 
22
17
  it 'has online doc' do
23
-
24
18
  end
25
19
 
26
20
  it 'has online doc for every version' do
27
-
28
21
  end
29
22
  end
@@ -5,7 +5,7 @@ describe 'Envelope' do
5
5
  it 'returns correct envelope' do
6
6
  call_api(:options, '/')
7
7
  expect(api_response.envelope.keys).to contain_exactly(
8
- *%i(version status response message errors)
8
+ *%i[version status response message errors]
9
9
  )
10
10
  end
11
11
 
@@ -21,7 +21,7 @@ describe 'Envelope' do
21
21
  it 'returns correct envelope' do
22
22
  call_api(:get, '/unknown_resource')
23
23
  expect(api_response.envelope.keys).to contain_exactly(
24
- *%i(status response message errors)
24
+ *%i[status response message errors]
25
25
  )
26
26
  end
27
27
 
data/spec/hooks_spec.rb CHANGED
@@ -7,7 +7,7 @@ describe HaveAPI::Hooks do
7
7
  has_hook :ret_hook
8
8
  has_hook :context_hook
9
9
  end
10
-
10
+
11
11
  class InstanceLevel
12
12
  include HaveAPI::Hookable
13
13
 
@@ -35,10 +35,10 @@ describe HaveAPI::Hooks do
35
35
  end
36
36
 
37
37
  else
38
- fail "unknown level '#{@level}'"
38
+ raise "unknown level '#{@level}'"
39
39
  end
40
40
  end
41
-
41
+
42
42
  shared_examples(:common) do
43
43
  it 'calls hooks' do
44
44
  called = false
@@ -51,10 +51,10 @@ describe HaveAPI::Hooks do
51
51
  call_hooks(:simple_hook)
52
52
  expect(called).to be true
53
53
  end
54
-
54
+
55
55
  it 'passes arguments' do
56
56
  called = false
57
-
57
+
58
58
  connect_hook(:arg_hook) do |ret, a, b, c|
59
59
  called = true
60
60
  expect([a, b, c]).to eq([1, 2, 3])
@@ -87,7 +87,7 @@ describe HaveAPI::Hooks do
87
87
  end
88
88
  end
89
89
 
90
- sum = call_hooks(:ret_hook, initial: {counter: 0})
90
+ sum = call_hooks(:ret_hook, initial: { counter: 0 })
91
91
  expect(sum[:counter]).to eq(5)
92
92
  end
93
93
 
@@ -113,7 +113,7 @@ describe HaveAPI::Hooks do
113
113
  @obj = ClassLevel
114
114
  @level = :class
115
115
  end
116
-
116
+
117
117
  include_examples :common
118
118
  end
119
119
 
@@ -123,23 +123,23 @@ describe HaveAPI::Hooks do
123
123
  @obj = InstanceLevel.new
124
124
  @level = :instance
125
125
  end
126
-
126
+
127
127
  include_examples :common
128
128
  end
129
-
129
+
130
130
  context 'only class hooks' do
131
131
  # FIXME: class hooks fail (that is correct, no class hooks are defined)
132
132
  # must find a way to test failure
133
- #include_examples :common
133
+ # include_examples :common
134
134
  end
135
-
135
+
136
136
  context 'only instance hooks' do
137
137
  before(:each) do
138
138
  @obj = InstanceLevel.new
139
139
  @level = :instance
140
140
  @method = :call_instance_hooks_for
141
141
  end
142
-
142
+
143
143
  include_examples :common
144
144
  end
145
145
  end
@@ -2,21 +2,21 @@ require 'time'
2
2
 
3
3
  describe 'Parameters::Typed' do
4
4
  def p_type(type)
5
- HaveAPI::Parameters::Typed.new(:param1, type: type)
5
+ HaveAPI::Parameters::Typed.new(:param1, type:)
6
6
  end
7
7
 
8
8
  def p_arg(arg = {})
9
- HaveAPI::Parameters::Typed.new(*[:param1, arg])
9
+ HaveAPI::Parameters::Typed.new(:param1, arg)
10
10
  end
11
11
 
12
12
  it 'does not change provided arguments' do
13
13
  kwargs = {
14
14
  label: 'Param 1',
15
15
  desc: 'Desc',
16
- required: true,
16
+ required: true
17
17
  }
18
18
  p_arg(kwargs)
19
- expect(kwargs.keys).to contain_exactly(*%i(label desc required))
19
+ expect(kwargs.keys).to contain_exactly(*%i[label desc required])
20
20
  end
21
21
 
22
22
  it 'automatically sets label' do
@@ -63,11 +63,11 @@ describe 'Parameters::Typed' do
63
63
  # Boolean
64
64
  p = p_type(Boolean)
65
65
 
66
- %w(true t yes y 1).each do |v|
66
+ %w[true t yes y 1].each do |v|
67
67
  expect(p.clean(v)).to be true
68
68
  end
69
69
 
70
- %w(false f no n 0).each do |v|
70
+ %w[false f no n 0].each do |v|
71
71
  expect(p.clean(v)).to be false
72
72
  end
73
73