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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +5 -0
  3. data/Rakefile +0 -1
  4. data/haveapi-client.gemspec +7 -10
  5. data/lib/haveapi/cli/action_state.rb +50 -51
  6. data/lib/haveapi/cli/authentication/base.rb +4 -9
  7. data/lib/haveapi/cli/authentication/basic.rb +3 -1
  8. data/lib/haveapi/cli/authentication/token.rb +7 -8
  9. data/lib/haveapi/cli/cli.rb +115 -127
  10. data/lib/haveapi/cli/command.rb +2 -4
  11. data/lib/haveapi/cli/commands/action_state_wait.rb +9 -9
  12. data/lib/haveapi/cli/example_formatter.rb +8 -8
  13. data/lib/haveapi/cli/output_formatter.rb +39 -36
  14. data/lib/haveapi/cli/utils.rb +5 -5
  15. data/lib/haveapi/cli.rb +1 -1
  16. data/lib/haveapi/client/action.rb +17 -20
  17. data/lib/haveapi/client/action_state.rb +3 -7
  18. data/lib/haveapi/client/authentication/base.rb +4 -7
  19. data/lib/haveapi/client/authentication/basic.rb +2 -2
  20. data/lib/haveapi/client/authentication/noauth.rb +0 -1
  21. data/lib/haveapi/client/authentication/token.rb +28 -27
  22. data/lib/haveapi/client/client.rb +12 -6
  23. data/lib/haveapi/client/communicator.rb +33 -35
  24. data/lib/haveapi/client/exceptions.rb +5 -9
  25. data/lib/haveapi/client/parameters/resource.rb +1 -0
  26. data/lib/haveapi/client/parameters/typed.rb +3 -5
  27. data/lib/haveapi/client/params.rb +8 -8
  28. data/lib/haveapi/client/resource.rb +12 -13
  29. data/lib/haveapi/client/resource_instance.rb +71 -72
  30. data/lib/haveapi/client/resource_instance_list.rb +2 -1
  31. data/lib/haveapi/client/response.rb +8 -8
  32. data/lib/haveapi/client/validator.rb +7 -8
  33. data/lib/haveapi/client/validators/confirmation.rb +1 -0
  34. data/lib/haveapi/client/validators/length.rb +1 -0
  35. data/lib/haveapi/client/validators/numericality.rb +2 -1
  36. data/lib/haveapi/client/validators/presence.rb +1 -0
  37. data/lib/haveapi/client/version.rb +2 -2
  38. data/lib/haveapi/client.rb +2 -2
  39. data/lib/restclient_ext/resource.rb +5 -5
  40. data/shell.nix +1 -1
  41. 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 ? :compatible
39
- : :imperfect
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 = {}, &block)
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
- &block
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
- tmp[:actions].each do |_, v|
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(POST PUT).include?(action.http_method)
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(GET DELETE).include?(action.http_method)
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.each do |k, v|
144
- get_params["_meta[#{k}]"] = v # FIXME: read _meta namespace from the description
145
-
146
- end if meta
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
- rescue RestClient::ResourceNotFound => e
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: response}
180
+ { status: true, response: }
182
181
  end
183
182
 
184
- def error(msg, errors={})
185
- {status: false, message: msg, errors: 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
- "Incompatible protocol version: the client uses v#{p_v} "+
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
- "Incompatible protocol version: the client uses v#{p_v} "+
219
- "while the API server uses v#{ret[:version]}"
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 ; end
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
- @response = response
9
- end
8
+ super("#{response.action.name} failed: #{response.message}")
10
9
 
11
- def message
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
@@ -16,6 +16,7 @@ module HaveAPI::Client
16
16
  end
17
17
 
18
18
  protected
19
+
19
20
  def coerce(v)
20
21
  if !v.is_a?(::Integer) && /\A\d+\z/ !~ v
21
22
  @errors << 'not a valid resource id'
@@ -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
- val = if type == 'Integer'
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(String Text).include?(type)
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 ; end
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
- @params[name] = Parameters::Resource.new(self, p, @data[name])
19
+ @params[name] = if p[:type] == 'Resource'
20
+ Parameters::Resource.new(self, p, @data[name])
21
21
 
22
- else
23
- @params[name] = Parameters::Typed.new(self, p, @data[name])
24
- end
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
- if !@params[name].valid?
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(block block_interval block_timeout).each do |p|
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.new(ret) unless ret.ok?
130
+ raise ActionFailed, ret unless ret.ok?
130
131
 
131
132
  return_value = case action.output && action.output_layout
132
- when :object
133
- ResourceInstance.new(@client, @api, self, action: action, response: ret)
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
- when :hash, :hash_list
139
- ret
136
+ when :object_list
137
+ ResourceInstanceList.new(@client, @api, self, action, ret)
140
138
 
141
- else
142
- ret
143
- end
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(new).include?(name.to_sym)
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 = response[:_meta] unless @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 = response.meta unless @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
- unless @persistent
41
- setup_from_clone(resource)
42
- define_implicit_attributes
43
- define_attributes(@action.input_params)
44
- end
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.new
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
- if @response.ok?
62
- @params = @response.response
63
- define_attributes
61
+ return nil unless @response.ok?
64
62
 
65
- else
66
- return nil
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.new(@response) if save.nil?
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.to_s}:#{object_id}:#{@resource._name}>"
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
- when 'Resource'
116
- @resource_instances[name] = find_association(param, @params[name])
117
-
118
- # id reader
119
- ensure_method(:"#{name}_id") do
120
- @params[name] && @params[name][ param[:value_id].to_sym ]
121
- end
122
-
123
- # id writer
124
- ensure_method(:"#{name}_id=") do |id|
125
- @params[name] ||= {}
126
- @params[name][ param[:value_id].to_sym ] = id
127
-
128
- @resource_instances[name] = find_association(
129
- param,
130
- {
131
- param[:value_id] => id,
132
- :_meta => {
133
- resolved: false,
134
- # TODO: this will not work for nested resources, as they have
135
- # multiple IDs
136
- path_params: [id],
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
- end
137
+ }
138
+ )
139
+ end
141
140
 
142
- # value reader
143
- ensure_method(name) do
144
- @resource_instances[name] && @resource_instances[name].resolve
145
- end
141
+ # value reader
142
+ ensure_method(name) do
143
+ @resource_instances[name] && @resource_instances[name].resolve
144
+ end
146
145
 
147
- # value writer
148
- ensure_method(:"#{name}=") do |obj|
149
- @params[name] ||= {}
150
- @params[name][ param[:value_id].to_sym ] = obj.method(param[:value_id]).call
151
- @params[name][ param[:value_label].to_sym ] = obj.method(param[:value_label]).call
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
- @resource_instances[name] = obj
154
- end
152
+ @resource_instances[name] = obj
153
+ end
155
154
 
156
- else
157
- # reader
158
- ensure_method(name) { @params[name] }
155
+ else
156
+ # reader
157
+ ensure_method(name) { @params[name] }
159
158
 
160
- # writer
161
- ensure_method(:"#{name}=") { |new_val| @params[name] = new_val }
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, &block)
168
- define_singleton_method(name, &block) unless respond_to?(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
- when 'Resource'
190
- ret[name] = @params[name][ param[:value_id].to_sym ]
187
+ ret[name] = case param[:type]
188
+ when 'Resource'
189
+ @params[name][ param[:value_id].to_sym ]
191
190
 
192
- else
193
- ret[name] = @params[name]
194
- end
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
- @client,
213
- @api,
214
- tmp,
215
- action: tmp.actions[:show],
216
- resolved: res_val[:_meta][:resolved],
217
- response: res_val[:_meta][:resolved] ? res_val : nil,
218
- meta: res_val[:_meta]
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: action, response: hash)
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
- when :object, :object_list, :hash, :hash_list
23
- @response[:response][@action.namespace(:output).to_sym]
24
- else
25
- @response[:response]
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(object hash).include?(@action.output_layout.to_sym)
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(list).include?(@action.layout.to_sym)
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(**kwargs, &block)
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, **kwargs, &block)
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 ; end
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
- fail "unsupported validator '#{name}'" if @validators[name].nil?
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] % { value: value }]
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
- def opts
47
- @opts
48
- end
46
+
47
+ attr_reader :opts
49
48
 
50
49
  def error(e)
51
50
  @errors ||= []
@@ -9,6 +9,7 @@ module HaveAPI::Client
9
9
 
10
10
  if opts[:equal]
11
11
  return false if params[other].nil?
12
+
12
13
  value == params[other].value
13
14
 
14
15
  else