haveapi 0.27.1 → 0.27.3

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: c1d65a2661353ff707b5b33f0bf8df446bfd4dcc6c669b5af8fdc46dbbf8a0a5
4
- data.tar.gz: ddb0c92670d615f22468c91c96f8e83e34cf53a3680cf55c588936aa95a34df7
3
+ metadata.gz: ec45b62af7fa8653e5f1a304b57746a9a2858db8b75c6a1d8a3deb5536cc7946
4
+ data.tar.gz: 0a991e394ccf4a4629f8d755fcfdfa9fd76af6fe37c696d361c1d9340ea8763c
5
5
  SHA512:
6
- metadata.gz: 908348858c2829a57531813ceb696c47768ec9a5e29133e8fb64e2c33613949ef70dd52468480a5a2e33c25c9c204541946ccfb982a17cec27656f4b184c2724
7
- data.tar.gz: 82e5b873d368caf4914895b24fa4e57d6b0b39c55357910c307496c535cacbdfebb35cd4036b2d07bb1627625a951f5e04fa440416f1eaa141980a22e943468e
6
+ metadata.gz: 693eb912e8215aa93c1c7b009475d91a752bfee1a2d4faeb33d59728168def03128dc7738c264e52f6cef3a87b7e7e11362a4da2f227deb057a9a89e50813705
7
+ data.tar.gz: e11fd922568a2ed631a702ec71e8e4631759bee27ecd122029e50af3fb389cde4f7167a0c26876b79b1db220d434b4c3117cb338e1a1fb3f529d85675fa91f1d
data/haveapi.gemspec CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
15
15
  s.required_ruby_version = ">= #{File.read('../../.ruby-version').strip}"
16
16
 
17
17
  s.add_dependency 'activesupport', '>= 7.1'
18
- s.add_dependency 'haveapi-client', '~> 0.27.1'
18
+ s.add_dependency 'haveapi-client', '~> 0.27.3'
19
19
  s.add_dependency 'json'
20
20
  s.add_dependency 'mail'
21
21
  s.add_dependency 'nesty', '~> 1.0'
@@ -142,15 +142,22 @@ module HaveAPI::ModelAdapters
142
142
 
143
143
  class Input < ::HaveAPI::ModelAdapter::Input
144
144
  def self.clean(model, raw, extra)
145
- return nil if raw.nil?
146
-
147
145
  original = raw
146
+ allow_null = if extra
147
+ extra.has_key?(:nullable) ? extra[:nullable] : extra[:optional]
148
+ end
149
+
150
+ if raw.nil?
151
+ return nil if allow_null
152
+
153
+ raise HaveAPI::ValidationError, "not a valid id #{original.inspect}"
154
+ end
148
155
 
149
156
  if raw.is_a?(String)
150
157
  stripped = raw.strip
151
158
 
152
159
  if stripped.empty?
153
- return nil if extra && extra[:optional]
160
+ return nil if allow_null
154
161
 
155
162
  raise HaveAPI::ValidationError, "not a valid id #{original.inspect}"
156
163
  end
@@ -5,7 +5,7 @@ module HaveAPI::Parameters
5
5
 
6
6
  def initialize(resource, name: nil, label: nil, desc: nil,
7
7
  choices: nil, value_id: :id, value_label: :label, required: nil,
8
- db_name: nil, fetch: nil)
8
+ db_name: nil, fetch: nil, nullable: nil)
9
9
  @resource = resource
10
10
  @resource_path = build_resource_path(resource)
11
11
  @name = name || resource.resource_name.underscore.to_sym
@@ -15,6 +15,7 @@ module HaveAPI::Parameters
15
15
  @value_id = value_id
16
16
  @value_label = value_label
17
17
  @required = required
18
+ @nullable = nullable
18
19
  @db_name = db_name
19
20
  @extra = {
20
21
  fetch:
@@ -33,6 +34,10 @@ module HaveAPI::Parameters
33
34
  !@required
34
35
  end
35
36
 
37
+ def nullable?
38
+ @nullable == true && optional?
39
+ end
40
+
36
41
  def show_action
37
42
  @resource::Show
38
43
  end
@@ -56,6 +61,7 @@ module HaveAPI::Parameters
56
61
 
57
62
  {
58
63
  required: required?,
64
+ nullable: nullable?,
59
65
  label: @label,
60
66
  description: @desc,
61
67
  type: 'Resource',
@@ -92,12 +98,18 @@ module HaveAPI::Parameters
92
98
  end
93
99
 
94
100
  def clean(raw)
101
+ if raw.nil?
102
+ return nil if nullable?
103
+
104
+ raise HaveAPI::ValidationError, 'cannot be null'
105
+ end
106
+
95
107
  if raw.is_a?(String)
96
108
  stripped = raw.strip
97
- return nil if stripped.empty? && optional?
109
+ return nil if stripped.empty? && nullable?
98
110
  end
99
111
 
100
- extra = @extra.merge(optional: optional?)
112
+ extra = @extra.merge(optional: optional?, nullable: nullable?)
101
113
 
102
114
  ::HaveAPI::ModelAdapter.for(
103
115
  show_action.input.layout, @resource.model
@@ -2,7 +2,7 @@ require 'date'
2
2
 
3
3
  module HaveAPI::Parameters
4
4
  class Typed
5
- ATTRIBUTES = %i[label desc type db_name default fill clean protected load_validators].freeze
5
+ ATTRIBUTES = %i[label desc type db_name default fill clean protected load_validators nullable].freeze
6
6
 
7
7
  attr_reader :name, :label, :desc, :type, :default
8
8
 
@@ -36,6 +36,10 @@ module HaveAPI::Parameters
36
36
  !required?
37
37
  end
38
38
 
39
+ def nullable?
40
+ @nullable == true && optional?
41
+ end
42
+
39
43
  def fill?
40
44
  @fill
41
45
  end
@@ -47,6 +51,7 @@ module HaveAPI::Parameters
47
51
  def describe(context)
48
52
  {
49
53
  required: required?,
54
+ nullable: nullable?,
50
55
  label: @label,
51
56
  description: @desc,
52
57
  type: @type ? @type.to_s : String.to_s,
@@ -76,9 +81,17 @@ module HaveAPI::Parameters
76
81
  return instance_exec(raw, &@clean) if @clean
77
82
 
78
83
  if raw.nil?
79
- @default
84
+ return nil if nullable?
85
+
86
+ raise HaveAPI::ValidationError, 'cannot be null'
87
+ end
88
+
89
+ if raw.is_a?(String)
90
+ stripped = raw.strip
91
+ return nil if stripped.empty? && nullable?
92
+ end
80
93
 
81
- elsif @type.nil?
94
+ if @type.nil?
82
95
  nil
83
96
 
84
97
  elsif @type == Integer
@@ -85,10 +85,11 @@ module HaveAPI::Resources
85
85
  float :timeout, label: 'Timeout', desc: 'in seconds', default: 15, fill: true
86
86
  float :update_in, label: 'Progress',
87
87
  desc: 'number of seconds after which the state is returned if the progress ' \
88
- 'has changed'
89
- bool :status, desc: 'status to check with if update_in is set'
90
- integer :current, desc: 'progress to check with if update_in is set'
91
- integer :total, desc: 'progress to check with if update_in is set'
88
+ 'has changed',
89
+ nullable: true
90
+ bool :status, desc: 'status to check with if update_in is set', nullable: true
91
+ integer :current, desc: 'progress to check with if update_in is set', nullable: true
92
+ integer :total, desc: 'progress to check with if update_in is set', nullable: true
92
93
  end
93
94
 
94
95
  output(:hash) do
@@ -1,4 +1,4 @@
1
1
  module HaveAPI
2
2
  PROTOCOL_VERSION = '2.0'.freeze
3
- VERSION = '0.27.1'.freeze
3
+ VERSION = '0.27.3'.freeze
4
4
  end
@@ -343,8 +343,8 @@ describe HaveAPI::ModelAdapters::ActiveRecord do
343
343
  expect(described_class::Input.clean(ARAdapterSpec::Environment, 1, {})).to eq(environment)
344
344
  expect(described_class::Input.clean(ARAdapterSpec::Environment, '1', {})).to eq(environment)
345
345
  expect(described_class::Input.clean(ARAdapterSpec::Environment, 1.0, {})).to eq(environment)
346
- expect(described_class::Input.clean(ARAdapterSpec::Environment, '', { optional: true })).to be_nil
347
- expect(described_class::Input.clean(ARAdapterSpec::Environment, ' ', { optional: true })).to be_nil
346
+ expect(described_class::Input.clean(ARAdapterSpec::Environment, '', { nullable: true })).to be_nil
347
+ expect(described_class::Input.clean(ARAdapterSpec::Environment, ' ', { nullable: true })).to be_nil
348
348
 
349
349
  expect do
350
350
  described_class::Input.clean(ARAdapterSpec::Environment, 'abc', {})
@@ -79,10 +79,14 @@ describe 'Parameters::Typed' do
79
79
  expect { p.clean('abc') }.to raise_error(HaveAPI::ValidationError)
80
80
  expect { p.clean('12abc') }.to raise_error(HaveAPI::ValidationError)
81
81
  expect { p.clean('') }.to raise_error(HaveAPI::ValidationError)
82
+ expect { p.clean(nil) }.to raise_error(HaveAPI::ValidationError)
82
83
  expect { p.clean('12.0') }.to raise_error(HaveAPI::ValidationError)
83
84
  expect { p.clean(12.3) }.to raise_error(HaveAPI::ValidationError)
84
85
  expect { p.clean(true) }.to raise_error(HaveAPI::ValidationError)
85
86
 
87
+ p = p_arg(type: Integer, required: true)
88
+ expect { p.clean('') }.to raise_error(HaveAPI::ValidationError)
89
+
86
90
  # Float
87
91
  p = p_type(Float)
88
92
  expect(p.clean('3.1456')).to eq(3.1456)
@@ -90,10 +94,14 @@ describe 'Parameters::Typed' do
90
94
  expect(p.clean(3)).to eq(3.0)
91
95
  expect { p.clean('abc') }.to raise_error(HaveAPI::ValidationError)
92
96
  expect { p.clean('') }.to raise_error(HaveAPI::ValidationError)
97
+ expect { p.clean(nil) }.to raise_error(HaveAPI::ValidationError)
93
98
  expect { p.clean('NaN') }.to raise_error(HaveAPI::ValidationError)
94
99
  expect { p.clean(Float::NAN) }.to raise_error(HaveAPI::ValidationError)
95
100
  expect { p.clean(Float::INFINITY) }.to raise_error(HaveAPI::ValidationError)
96
101
 
102
+ p = p_arg(type: Float, required: true)
103
+ expect { p.clean('') }.to raise_error(HaveAPI::ValidationError)
104
+
97
105
  # Boolean
98
106
  p = p_type(Boolean)
99
107
 
@@ -110,8 +118,12 @@ describe 'Parameters::Typed' do
110
118
  expect(p.clean(' YES ')).to be true
111
119
  expect { p.clean('maybe') }.to raise_error(HaveAPI::ValidationError)
112
120
  expect { p.clean('') }.to raise_error(HaveAPI::ValidationError)
121
+ expect { p.clean(nil) }.to raise_error(HaveAPI::ValidationError)
113
122
  expect { p.clean(2) }.to raise_error(HaveAPI::ValidationError)
114
123
 
124
+ p = p_arg(type: Boolean, required: true)
125
+ expect { p.clean('') }.to raise_error(HaveAPI::ValidationError)
126
+
115
127
  # Datetime
116
128
  p = p_type(Datetime)
117
129
  t = Time.now
@@ -120,10 +132,15 @@ describe 'Parameters::Typed' do
120
132
  expect(p.clean(t.iso8601)).to eq(t2)
121
133
  expect { p.clean('bzz') }.to raise_error(HaveAPI::ValidationError)
122
134
  expect { p.clean('') }.to raise_error(HaveAPI::ValidationError)
135
+ expect { p.clean(nil) }.to raise_error(HaveAPI::ValidationError)
136
+
137
+ p = p_arg(type: Datetime, required: true)
138
+ expect { p.clean('') }.to raise_error(HaveAPI::ValidationError)
123
139
 
124
140
  # String, Text
125
141
  p = p_type(String)
126
142
  expect(p.clean('bzz')).to eq('bzz')
143
+ expect(p.clean('')).to eq('')
127
144
  expect(p.clean(123)).to eq('123')
128
145
  expect(p.clean(true)).to eq('true')
129
146
  expect { p.clean([]) }.to raise_error(HaveAPI::ValidationError)
@@ -131,17 +148,38 @@ describe 'Parameters::Typed' do
131
148
 
132
149
  p = p_type(Text)
133
150
  expect(p.clean('bzz')).to eq('bzz')
151
+ expect(p.clean('')).to eq('')
134
152
  expect(p.clean(123)).to eq('123')
135
153
  expect(p.clean(true)).to eq('true')
136
154
  expect { p.clean([]) }.to raise_error(HaveAPI::ValidationError)
137
155
  expect { p.clean({}) }.to raise_error(HaveAPI::ValidationError)
138
156
 
139
- # Defaults
140
- p = p_type(String)
157
+ # Nullable
158
+ p = p_arg(type: Integer, nullable: true)
159
+ expect(p.clean('')).to be_nil
141
160
  expect(p.clean(nil)).to be_nil
142
161
 
162
+ p = p_arg(type: Float, nullable: true)
163
+ expect(p.clean('')).to be_nil
164
+ expect(p.clean(nil)).to be_nil
165
+
166
+ p = p_arg(type: Boolean, nullable: true)
167
+ expect(p.clean('')).to be_nil
168
+ expect(p.clean(nil)).to be_nil
169
+
170
+ p = p_arg(type: Datetime, nullable: true)
171
+ expect(p.clean('')).to be_nil
172
+ expect(p.clean(nil)).to be_nil
173
+
174
+ p = p_arg(type: String, nullable: true)
175
+ expect(p.clean('')).to be_nil
176
+ expect(p.clean(nil)).to be_nil
143
177
  p.patch(default: 'bazinga')
144
- expect(p.clean(nil)).to eq('bazinga')
178
+ expect(p.clean(nil)).to be_nil
179
+
180
+ p = p_arg(type: Text, nullable: true)
181
+ expect(p.clean('')).to be_nil
182
+ expect(p.clean(nil)).to be_nil
145
183
  end
146
184
 
147
185
  it 'can be protected' do
@@ -457,6 +457,54 @@ module HaveAPI
457
457
  end
458
458
  end
459
459
 
460
+ define_action(:EchoOptional) do
461
+ extend DocFilter
462
+ route 'echo_optional'
463
+ http_method :post
464
+ input(:hash) do
465
+ datetime :dt, required: false, nullable: true
466
+ end
467
+ output(:hash) do
468
+ bool :dt_provided, required: true
469
+ bool :dt_nil, required: true
470
+ datetime :dt
471
+ end
472
+ authorize { allow }
473
+
474
+ def exec
475
+ ret = {
476
+ dt_provided: input.has_key?(:dt),
477
+ dt_nil: input[:dt].nil?
478
+ }
479
+ ret[:dt] = input[:dt] unless input[:dt].nil?
480
+ ret
481
+ end
482
+ end
483
+
484
+ define_action(:EchoOptionalGet) do
485
+ extend DocFilter
486
+ route 'echo_optional_get'
487
+ http_method :get
488
+ input(:hash) do
489
+ datetime :dt, required: false, nullable: true
490
+ end
491
+ output(:hash) do
492
+ bool :dt_provided, required: true
493
+ bool :dt_nil, required: true
494
+ datetime :dt
495
+ end
496
+ authorize { allow }
497
+
498
+ def exec
499
+ ret = {
500
+ dt_provided: input.has_key?(:dt),
501
+ dt_nil: input[:dt].nil?
502
+ }
503
+ ret[:dt] = input[:dt] unless input[:dt].nil?
504
+ ret
505
+ end
506
+ end
507
+
460
508
  define_action(:EchoResource) do
461
509
  extend DocFilter
462
510
  route 'echo_resource'
@@ -479,7 +527,7 @@ module HaveAPI
479
527
  route 'echo_resource_optional'
480
528
  http_method :get
481
529
  input(:hash) do
482
- resource HaveAPI::ClientTestAPI::Resources::Project, required: false
530
+ resource HaveAPI::ClientTestAPI::Resources::Project, required: false, nullable: true
483
531
  end
484
532
  output(:hash) do
485
533
  bool :project_provided, required: true
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haveapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.27.1
4
+ version: 0.27.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jakub Skokan
@@ -29,14 +29,14 @@ dependencies:
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: 0.27.1
32
+ version: 0.27.3
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 0.27.1
39
+ version: 0.27.3
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: json
42
42
  requirement: !ruby/object:Gem::Requirement