haveapi-client 0.20.0 → 0.21.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +5 -0
- data/Rakefile +0 -1
- data/haveapi-client.gemspec +7 -10
- data/lib/haveapi/cli/action_state.rb +50 -51
- data/lib/haveapi/cli/authentication/base.rb +4 -9
- data/lib/haveapi/cli/authentication/basic.rb +3 -1
- data/lib/haveapi/cli/authentication/token.rb +7 -8
- data/lib/haveapi/cli/cli.rb +115 -127
- data/lib/haveapi/cli/command.rb +2 -4
- data/lib/haveapi/cli/commands/action_state_wait.rb +9 -9
- data/lib/haveapi/cli/example_formatter.rb +8 -8
- data/lib/haveapi/cli/output_formatter.rb +39 -36
- data/lib/haveapi/cli/utils.rb +5 -5
- data/lib/haveapi/cli.rb +1 -1
- data/lib/haveapi/client/action.rb +17 -20
- data/lib/haveapi/client/action_state.rb +3 -7
- data/lib/haveapi/client/authentication/base.rb +4 -7
- data/lib/haveapi/client/authentication/basic.rb +2 -2
- data/lib/haveapi/client/authentication/noauth.rb +0 -1
- data/lib/haveapi/client/authentication/token.rb +28 -27
- data/lib/haveapi/client/client.rb +12 -6
- data/lib/haveapi/client/communicator.rb +33 -35
- data/lib/haveapi/client/exceptions.rb +5 -9
- data/lib/haveapi/client/parameters/resource.rb +1 -0
- data/lib/haveapi/client/parameters/typed.rb +3 -5
- data/lib/haveapi/client/params.rb +8 -8
- data/lib/haveapi/client/resource.rb +12 -13
- data/lib/haveapi/client/resource_instance.rb +71 -72
- data/lib/haveapi/client/resource_instance_list.rb +2 -1
- data/lib/haveapi/client/response.rb +8 -8
- data/lib/haveapi/client/validator.rb +7 -8
- data/lib/haveapi/client/validators/confirmation.rb +1 -0
- data/lib/haveapi/client/validators/length.rb +1 -0
- data/lib/haveapi/client/validators/numericality.rb +2 -1
- data/lib/haveapi/client/validators/presence.rb +1 -0
- data/lib/haveapi/client/version.rb +2 -2
- data/lib/haveapi/client.rb +2 -2
- data/lib/restclient_ext/resource.rb +5 -5
- data/shell.nix +1 -1
- metadata +15 -43
@@ -34,10 +34,12 @@ module HaveAPI::Client
|
|
34
34
|
# @return [:imperfect] if minor version differs
|
35
35
|
# @return [false] if not compatible
|
36
36
|
def compatible?
|
37
|
-
description_for(path_for, {describe: :versions})
|
38
|
-
@proto_version == HaveAPI::Client::PROTOCOL_VERSION
|
39
|
-
|
40
|
-
|
37
|
+
description_for(path_for, { describe: :versions })
|
38
|
+
if @proto_version == HaveAPI::Client::PROTOCOL_VERSION
|
39
|
+
:compatible
|
40
|
+
else
|
41
|
+
:imperfect
|
42
|
+
end
|
41
43
|
rescue ProtocolError
|
42
44
|
false
|
43
45
|
end
|
@@ -45,14 +47,14 @@ module HaveAPI::Client
|
|
45
47
|
# Authenticate user with selected +auth_method+.
|
46
48
|
# +auth_method+ is a name of registered authentication provider.
|
47
49
|
# +options+ are specific for each authentication provider.
|
48
|
-
def authenticate(auth_method, options = {}, &
|
50
|
+
def authenticate(auth_method, options = {}, &)
|
49
51
|
desc = describe_api(@version)
|
50
52
|
|
51
53
|
@auth = self.class.auth_methods[auth_method].new(
|
52
54
|
self,
|
53
55
|
desc[:authentication][auth_method],
|
54
56
|
options,
|
55
|
-
&
|
57
|
+
&
|
56
58
|
)
|
57
59
|
@rest = @auth.resource || @rest
|
58
60
|
end
|
@@ -62,11 +64,11 @@ module HaveAPI::Client
|
|
62
64
|
end
|
63
65
|
|
64
66
|
def available_versions
|
65
|
-
description_for(path_for, {describe: :versions})
|
67
|
+
description_for(path_for, { describe: :versions })
|
66
68
|
end
|
67
69
|
|
68
|
-
def describe_api(v=nil)
|
69
|
-
description_for(path_for(v), v.nil? ? {describe: :default} : {})
|
70
|
+
def describe_api(v = nil)
|
71
|
+
description_for(path_for(v), v.nil? ? { describe: :default } : {})
|
70
72
|
end
|
71
73
|
|
72
74
|
def describe_resource(path)
|
@@ -97,7 +99,7 @@ module HaveAPI::Client
|
|
97
99
|
a = tmp[:actions][action]
|
98
100
|
|
99
101
|
unless a # search in aliases
|
100
|
-
|
102
|
+
tmp[:actions].each_value do |v|
|
101
103
|
if v[:aliases].include?(action.to_s)
|
102
104
|
a = v
|
103
105
|
break
|
@@ -124,43 +126,39 @@ module HaveAPI::Client
|
|
124
126
|
params.delete(:meta)
|
125
127
|
end
|
126
128
|
|
127
|
-
if %w
|
129
|
+
if %w[POST PUT].include?(action.http_method)
|
128
130
|
ns = {}
|
129
131
|
ns[input_namespace] = params if input_namespace
|
130
132
|
ns[:_meta] = meta if meta
|
131
133
|
ns.update(@auth.request_payload)
|
132
134
|
|
133
135
|
args << ns.to_json
|
134
|
-
args << {content_type: :json, accept: :json, user_agent: @identity}.update(@auth.request_headers)
|
136
|
+
args << { content_type: :json, accept: :json, user_agent: @identity }.update(@auth.request_headers)
|
135
137
|
|
136
|
-
elsif %w
|
138
|
+
elsif %w[GET DELETE].include?(action.http_method)
|
137
139
|
get_params = {}
|
138
140
|
|
139
141
|
params.each do |k, v|
|
140
142
|
get_params["#{input_namespace}[#{k}]"] = v
|
141
143
|
end
|
142
144
|
|
143
|
-
meta
|
144
|
-
|
145
|
-
|
146
|
-
|
145
|
+
if meta
|
146
|
+
meta.each do |k, v|
|
147
|
+
get_params["_meta[#{k}]"] = v # FIXME: read _meta namespace from the description
|
148
|
+
end
|
149
|
+
end
|
147
150
|
|
148
|
-
args << {params: get_params.update(@auth.request_query_params), accept: :json, user_agent: @identity}.update(@auth.request_headers)
|
151
|
+
args << { params: get_params.update(@auth.request_query_params), accept: :json, user_agent: @identity }.update(@auth.request_headers)
|
149
152
|
end
|
150
153
|
|
151
154
|
begin
|
152
155
|
response = parse(@rest[action.prepared_path].method(action.http_method.downcase.to_sym).call(*args))
|
153
|
-
|
154
156
|
rescue RestClient::Forbidden
|
155
157
|
return error('Access forbidden. Bad user name or password? Not authorized?')
|
156
|
-
|
157
|
-
|
158
|
-
response = parse(e.http_body)
|
159
|
-
|
160
|
-
rescue RestClient::BadRequest => e
|
158
|
+
rescue RestClient::ResourceNotFound,
|
159
|
+
RestClient::BadRequest => e
|
161
160
|
response = parse(e.http_body)
|
162
|
-
|
163
|
-
rescue => e
|
161
|
+
rescue StandardError => e
|
164
162
|
return error("Fatal API error: #{e.inspect}")
|
165
163
|
end
|
166
164
|
|
@@ -177,15 +175,16 @@ module HaveAPI::Client
|
|
177
175
|
end
|
178
176
|
|
179
177
|
private
|
178
|
+
|
180
179
|
def ok(response)
|
181
|
-
{status: true, response:
|
180
|
+
{ status: true, response: }
|
182
181
|
end
|
183
182
|
|
184
|
-
def error(msg, errors={})
|
185
|
-
{status: false, message: msg, errors:
|
183
|
+
def error(msg, errors = {})
|
184
|
+
{ status: false, message: msg, errors: }
|
186
185
|
end
|
187
186
|
|
188
|
-
def path_for(v=nil, r=nil)
|
187
|
+
def path_for(v = nil, r = nil)
|
189
188
|
ret = '/'
|
190
189
|
|
191
190
|
ret += "v#{v}/" if v
|
@@ -194,7 +193,7 @@ module HaveAPI::Client
|
|
194
193
|
ret
|
195
194
|
end
|
196
195
|
|
197
|
-
def description_for(path, query_params={})
|
196
|
+
def description_for(path, query_params = {})
|
198
197
|
ret = parse(@rest[path].get_options({
|
199
198
|
params: @auth.request_payload.update(@auth.request_query_params).update(query_params),
|
200
199
|
user_agent: @identity
|
@@ -206,8 +205,7 @@ module HaveAPI::Client
|
|
206
205
|
|
207
206
|
unless ret[:version]
|
208
207
|
raise ProtocolError,
|
209
|
-
|
210
|
-
"while the API server uses an unspecified version (pre 1.0)"
|
208
|
+
"Incompatible protocol version: the client uses v#{p_v} while the API server uses an unspecified version (pre 1.0)"
|
211
209
|
end
|
212
210
|
|
213
211
|
major1, minor1 = ret[:version].split('.')
|
@@ -215,8 +213,8 @@ module HaveAPI::Client
|
|
215
213
|
|
216
214
|
if major1 != major2
|
217
215
|
raise ProtocolError,
|
218
|
-
|
219
|
-
|
216
|
+
"Incompatible protocol version: the client uses v#{p_v} " \
|
217
|
+
"while the API server uses v#{ret[:version]}"
|
220
218
|
end
|
221
219
|
|
222
220
|
warn "The client uses protocol v#{p_v} while the API server uses v#{ret[:version]}"
|
@@ -1,15 +1,13 @@
|
|
1
1
|
module HaveAPI::Client
|
2
|
-
class ProtocolError < StandardError
|
2
|
+
class ProtocolError < StandardError; end
|
3
3
|
|
4
4
|
class ActionFailed < StandardError
|
5
5
|
attr_reader :response
|
6
6
|
|
7
7
|
def initialize(response)
|
8
|
-
|
9
|
-
end
|
8
|
+
super("#{response.action.name} failed: #{response.message}")
|
10
9
|
|
11
|
-
|
12
|
-
"#{@response.action.name} failed: #{@response.message}"
|
10
|
+
@response = response
|
13
11
|
end
|
14
12
|
end
|
15
13
|
|
@@ -17,12 +15,10 @@ module HaveAPI::Client
|
|
17
15
|
attr_reader :errors
|
18
16
|
|
19
17
|
def initialize(action, errors)
|
18
|
+
super("#{action.name} failed: input parameters not valid")
|
19
|
+
|
20
20
|
@action = action
|
21
21
|
@errors = errors
|
22
22
|
end
|
23
|
-
|
24
|
-
def message
|
25
|
-
"#{@action.name} failed: input parameters not valid"
|
26
|
-
end
|
27
23
|
end
|
28
24
|
end
|
@@ -40,10 +40,11 @@ module HaveAPI::Client
|
|
40
40
|
end
|
41
41
|
|
42
42
|
protected
|
43
|
+
|
43
44
|
def coerce(raw)
|
44
45
|
type = @desc[:type]
|
45
46
|
|
46
|
-
|
47
|
+
if type == 'Integer'
|
47
48
|
raw.to_i
|
48
49
|
|
49
50
|
elsif type == 'Float'
|
@@ -62,21 +63,18 @@ module HaveAPI::Client
|
|
62
63
|
else
|
63
64
|
begin
|
64
65
|
DateTime.iso8601(raw).to_time
|
65
|
-
|
66
66
|
rescue ArgumentError
|
67
67
|
@errors << 'not in ISO 8601 format'
|
68
68
|
nil
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
elsif %w
|
72
|
+
elsif %w[String Text].include?(type)
|
73
73
|
raw.to_s
|
74
74
|
|
75
75
|
else
|
76
76
|
raw
|
77
77
|
end
|
78
|
-
|
79
|
-
val
|
80
78
|
end
|
81
79
|
end
|
82
80
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module HaveAPI::Client
|
2
|
-
module Parameters
|
2
|
+
module Parameters; end
|
3
3
|
|
4
4
|
class Params
|
5
5
|
attr_reader :errors, :params
|
@@ -16,12 +16,12 @@ module HaveAPI::Client
|
|
16
16
|
@action.input_params.each do |name, p|
|
17
17
|
next unless @data.has_key?(name)
|
18
18
|
|
19
|
-
if p[:type] == 'Resource'
|
20
|
-
|
19
|
+
@params[name] = if p[:type] == 'Resource'
|
20
|
+
Parameters::Resource.new(self, p, @data[name])
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
else
|
23
|
+
Parameters::Typed.new(self, p, @data[name])
|
24
|
+
end
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -36,10 +36,9 @@ module HaveAPI::Client
|
|
36
36
|
next
|
37
37
|
end
|
38
38
|
|
39
|
-
|
39
|
+
unless @params[name].valid?
|
40
40
|
error(name, @params[name].errors)
|
41
41
|
end
|
42
|
-
|
43
42
|
end
|
44
43
|
|
45
44
|
@errors.empty?
|
@@ -58,6 +57,7 @@ module HaveAPI::Client
|
|
58
57
|
end
|
59
58
|
|
60
59
|
protected
|
60
|
+
|
61
61
|
def error(param, msg)
|
62
62
|
@errors[param] ||= []
|
63
63
|
|
@@ -71,6 +71,7 @@ module HaveAPI::Client
|
|
71
71
|
end
|
72
72
|
|
73
73
|
protected
|
74
|
+
|
74
75
|
# Define access/write methods for action +action+.
|
75
76
|
def define_action(action)
|
76
77
|
action.aliases(true).each do |name|
|
@@ -116,7 +117,7 @@ module HaveAPI::Client
|
|
116
117
|
if user_params.has_key?(:meta)
|
117
118
|
meta = user_params[:meta]
|
118
119
|
|
119
|
-
%i
|
120
|
+
%i[block block_interval block_timeout].each do |p|
|
120
121
|
client_opts[p] = meta.delete(p) if meta.has_key?(p)
|
121
122
|
end
|
122
123
|
end
|
@@ -126,21 +127,18 @@ module HaveAPI::Client
|
|
126
127
|
|
127
128
|
ret = Response.new(action, action.execute(input_params))
|
128
129
|
|
129
|
-
raise ActionFailed
|
130
|
+
raise ActionFailed, ret unless ret.ok?
|
130
131
|
|
131
132
|
return_value = case action.output && action.output_layout
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
when :object_list
|
136
|
-
ResourceInstanceList.new(@client, @api, self, action, ret)
|
133
|
+
when :object
|
134
|
+
ResourceInstance.new(@client, @api, self, action:, response: ret)
|
137
135
|
|
138
|
-
|
139
|
-
|
136
|
+
when :object_list
|
137
|
+
ResourceInstanceList.new(@client, @api, self, action, ret)
|
140
138
|
|
141
|
-
|
142
|
-
|
143
|
-
|
139
|
+
else # :hash, :hash_list
|
140
|
+
ret
|
141
|
+
end
|
144
142
|
|
145
143
|
if action.blocking? && client_opts[:block]
|
146
144
|
wait_opts = {}
|
@@ -165,7 +163,8 @@ module HaveAPI::Client
|
|
165
163
|
# Called before defining a method named +name+ that will
|
166
164
|
# invoke +action+.
|
167
165
|
def define_method?(action, name)
|
168
|
-
return false if %i
|
166
|
+
return false if %i[new].include?(name.to_sym)
|
167
|
+
|
169
168
|
true
|
170
169
|
end
|
171
170
|
|
@@ -24,28 +24,28 @@ module HaveAPI::Client
|
|
24
24
|
if response.is_a?(Hash)
|
25
25
|
@params = response
|
26
26
|
@prepared_args = response[:_meta][:path_params]
|
27
|
-
@meta
|
27
|
+
@meta ||= response[:_meta]
|
28
28
|
|
29
29
|
else
|
30
30
|
@response = response
|
31
31
|
@params = response.response
|
32
32
|
@prepared_args = response.meta[:path_params]
|
33
|
-
@meta
|
33
|
+
@meta ||= response.meta
|
34
34
|
end
|
35
35
|
|
36
36
|
setup_from_clone(resource)
|
37
37
|
define_attributes
|
38
38
|
end
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
return if @persistent
|
41
|
+
|
42
|
+
setup_from_clone(resource)
|
43
|
+
define_implicit_attributes
|
44
|
+
define_attributes(@action.input_params)
|
45
45
|
end
|
46
46
|
|
47
47
|
def new
|
48
|
-
raise NoMethodError
|
48
|
+
raise NoMethodError
|
49
49
|
end
|
50
50
|
|
51
51
|
# Invoke +create+ action if the object is not persistent,
|
@@ -58,13 +58,10 @@ module HaveAPI::Client
|
|
58
58
|
@action.provide_args
|
59
59
|
@response = Response.new(@action, @action.execute(attributes_for_api(@action)))
|
60
60
|
|
61
|
-
|
62
|
-
@params = @response.response
|
63
|
-
define_attributes
|
61
|
+
return nil unless @response.ok?
|
64
62
|
|
65
|
-
|
66
|
-
|
67
|
-
end
|
63
|
+
@params = @response.response
|
64
|
+
define_attributes
|
68
65
|
|
69
66
|
@persistent = true
|
70
67
|
self
|
@@ -73,7 +70,8 @@ module HaveAPI::Client
|
|
73
70
|
|
74
71
|
# Call #save and raise ActionFailed if it fails.
|
75
72
|
def save!
|
76
|
-
raise ActionFailed
|
73
|
+
raise ActionFailed, @response if save.nil?
|
74
|
+
|
77
75
|
self
|
78
76
|
end
|
79
77
|
|
@@ -104,68 +102,69 @@ module HaveAPI::Client
|
|
104
102
|
end
|
105
103
|
|
106
104
|
def to_s
|
107
|
-
"<#{self.class
|
105
|
+
"<#{self.class}:#{object_id}:#{@resource._name}>"
|
108
106
|
end
|
109
107
|
|
110
108
|
protected
|
109
|
+
|
111
110
|
# Define access/writer methods for object attributes.
|
112
111
|
def define_attributes(params = nil)
|
113
112
|
(params || @action.params).each do |name, param|
|
114
113
|
case param[:type]
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
},
|
114
|
+
when 'Resource'
|
115
|
+
@resource_instances[name] = find_association(param, @params[name])
|
116
|
+
|
117
|
+
# id reader
|
118
|
+
ensure_method(:"#{name}_id") do
|
119
|
+
@params[name] && @params[name][ param[:value_id].to_sym ]
|
120
|
+
end
|
121
|
+
|
122
|
+
# id writer
|
123
|
+
ensure_method(:"#{name}_id=") do |id|
|
124
|
+
@params[name] ||= {}
|
125
|
+
@params[name][ param[:value_id].to_sym ] = id
|
126
|
+
|
127
|
+
@resource_instances[name] = find_association(
|
128
|
+
param,
|
129
|
+
{
|
130
|
+
param[:value_id] => id,
|
131
|
+
:_meta => {
|
132
|
+
resolved: false,
|
133
|
+
# TODO: this will not work for nested resources, as they have
|
134
|
+
# multiple IDs
|
135
|
+
path_params: [id]
|
138
136
|
}
|
139
|
-
|
140
|
-
|
137
|
+
}
|
138
|
+
)
|
139
|
+
end
|
141
140
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
141
|
+
# value reader
|
142
|
+
ensure_method(name) do
|
143
|
+
@resource_instances[name] && @resource_instances[name].resolve
|
144
|
+
end
|
146
145
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
146
|
+
# value writer
|
147
|
+
ensure_method(:"#{name}=") do |obj|
|
148
|
+
@params[name] ||= {}
|
149
|
+
@params[name][ param[:value_id].to_sym ] = obj.method(param[:value_id]).call
|
150
|
+
@params[name][ param[:value_label].to_sym ] = obj.method(param[:value_label]).call
|
152
151
|
|
153
|
-
|
154
|
-
|
152
|
+
@resource_instances[name] = obj
|
153
|
+
end
|
155
154
|
|
156
|
-
|
157
|
-
|
158
|
-
|
155
|
+
else
|
156
|
+
# reader
|
157
|
+
ensure_method(name) { @params[name] }
|
159
158
|
|
160
|
-
|
161
|
-
|
159
|
+
# writer
|
160
|
+
ensure_method(:"#{name}=") { |new_val| @params[name] = new_val }
|
162
161
|
end
|
163
162
|
end
|
164
163
|
end
|
165
164
|
|
166
165
|
# Define method +name+ with +block+ if it isn't defined yet.
|
167
|
-
def ensure_method(name, &
|
168
|
-
define_singleton_method(name, &
|
166
|
+
def ensure_method(name, &)
|
167
|
+
define_singleton_method(name, &) unless respond_to?(name)
|
169
168
|
end
|
170
169
|
|
171
170
|
# Define nil references to resource attributes.
|
@@ -185,13 +184,13 @@ module HaveAPI::Client
|
|
185
184
|
return ret if action.input_layout != :object
|
186
185
|
|
187
186
|
action.input_params.each do |name, param|
|
188
|
-
case param[:type]
|
189
|
-
|
190
|
-
|
187
|
+
ret[name] = case param[:type]
|
188
|
+
when 'Resource'
|
189
|
+
@params[name][ param[:value_id].to_sym ]
|
191
190
|
|
192
|
-
|
193
|
-
|
194
|
-
|
191
|
+
else
|
192
|
+
@params[name]
|
193
|
+
end
|
195
194
|
end
|
196
195
|
|
197
196
|
ret
|
@@ -209,13 +208,13 @@ module HaveAPI::Client
|
|
209
208
|
|
210
209
|
# FIXME: read _meta namespace from description
|
211
210
|
ResourceInstance.new(
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
211
|
+
@client,
|
212
|
+
@api,
|
213
|
+
tmp,
|
214
|
+
action: tmp.actions[:show],
|
215
|
+
resolved: res_val[:_meta][:resolved],
|
216
|
+
response: res_val[:_meta][:resolved] ? res_val : nil,
|
217
|
+
meta: res_val[:_meta]
|
219
218
|
)
|
220
219
|
end
|
221
220
|
|
@@ -2,10 +2,11 @@ module HaveAPI::Client
|
|
2
2
|
# A list of ResourceInstance objects.
|
3
3
|
class ResourceInstanceList < Array
|
4
4
|
def initialize(client, api, resource, action, response)
|
5
|
+
super()
|
5
6
|
@response = response
|
6
7
|
|
7
8
|
response.response.each do |hash|
|
8
|
-
self << ResourceInstance.new(client, api, resource, action
|
9
|
+
self << ResourceInstance.new(client, api, resource, action:, response: hash)
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
@@ -19,10 +19,10 @@ class HaveAPI::Client::Response
|
|
19
19
|
|
20
20
|
def response
|
21
21
|
case @action.output_layout
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
when :object, :object_list, :hash, :hash_list
|
23
|
+
@response[:response][@action.namespace(:output).to_sym]
|
24
|
+
else
|
25
|
+
@response[:response]
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -44,7 +44,7 @@ class HaveAPI::Client::Response
|
|
44
44
|
|
45
45
|
# Access namespaced params directly.
|
46
46
|
def [](key)
|
47
|
-
return unless %i
|
47
|
+
return unless %i[object hash].include?(@action.output_layout.to_sym)
|
48
48
|
|
49
49
|
@response[:response][@action.namespace(:output).to_sym][key]
|
50
50
|
end
|
@@ -52,7 +52,7 @@ class HaveAPI::Client::Response
|
|
52
52
|
# Iterate over namespaced items directly. Works for only for
|
53
53
|
# object_list or hash_list.
|
54
54
|
def each
|
55
|
-
return unless %i
|
55
|
+
return unless %i[list].include?(@action.layout.to_sym)
|
56
56
|
|
57
57
|
@response[:response][@action.namespace(:output).to_sym].each
|
58
58
|
end
|
@@ -61,10 +61,10 @@ class HaveAPI::Client::Response
|
|
61
61
|
# it is regularly called with the action's state.
|
62
62
|
#
|
63
63
|
# @see HaveAPI::Client::Action#wait_for_completion
|
64
|
-
def wait_for_completion(
|
64
|
+
def wait_for_completion(**, &)
|
65
65
|
id = meta[:action_state_id]
|
66
66
|
return nil unless id
|
67
67
|
|
68
|
-
HaveAPI::Client::Action.wait_for_completion(@action.client, id,
|
68
|
+
HaveAPI::Client::Action.wait_for_completion(@action.client, id, **, &)
|
69
69
|
end
|
70
70
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module HaveAPI::Client
|
2
|
-
module Validators
|
2
|
+
module Validators; end
|
3
3
|
|
4
4
|
class Validator
|
5
5
|
class << self
|
6
6
|
def name(v)
|
7
7
|
Validator.register(v, self)
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
def register(name, klass)
|
11
11
|
@validators ||= {}
|
12
12
|
@validators[name] = klass
|
@@ -14,9 +14,9 @@ module HaveAPI::Client
|
|
14
14
|
|
15
15
|
def validate(validators, param, other_params)
|
16
16
|
ret = []
|
17
|
-
|
17
|
+
|
18
18
|
validators.each do |name, desc|
|
19
|
-
|
19
|
+
raise "unsupported validator '#{name}'" if @validators[name].nil?
|
20
20
|
|
21
21
|
v = @validators[name].new(desc, param, other_params)
|
22
22
|
ret.concat(v.errors) unless v.valid?
|
@@ -35,7 +35,7 @@ module HaveAPI::Client
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def errors
|
38
|
-
@errors || [opts[:message]
|
38
|
+
@errors || [format(opts[:message], value:)]
|
39
39
|
end
|
40
40
|
|
41
41
|
def valid?
|
@@ -43,9 +43,8 @@ module HaveAPI::Client
|
|
43
43
|
end
|
44
44
|
|
45
45
|
protected
|
46
|
-
|
47
|
-
|
48
|
-
end
|
46
|
+
|
47
|
+
attr_reader :opts
|
49
48
|
|
50
49
|
def error(e)
|
51
50
|
@errors ||= []
|