flexirest 1.6.7 → 1.6.8

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
  SHA1:
3
- metadata.gz: d07c8260f4147a07a88031a028a1062a40f8fecc
4
- data.tar.gz: db5f43a0ac0a8a2dc7b7e60dd8742d83ec614ddf
3
+ metadata.gz: 48c8e263cf0b1c959599454ce360b612b279b900
4
+ data.tar.gz: eba90a77d94f9d8e29f651ec1a1b7815a10b4aa6
5
5
  SHA512:
6
- metadata.gz: abd6a9d4e215781f4f2a421cd796bd2c76878e47fb969c5191092d72c6ad6e613cef9bba5cf005a6651fadaa4637ba8475160c3f41eb089b3007994ea326d94b
7
- data.tar.gz: 3934022f4a3ee6a28e6f4290a7228fe89a9f6cc116d00ceb6746c1fe29e6b4b4756c25277e200549f8c0b1bfb6577342343841d5104422b4f3041c8f3ae58084
6
+ metadata.gz: a43bc7600fd621a71e595e55b1aebddc19feda4eae959a376c429eb4498e35d2f55c64c62c5a97f4769a98036d8f31a207da90e72de94133d38a5ad5c680b080
7
+ data.tar.gz: 895458b577307cf2a2be5681fb827979847d61b13e36f89c236a3c1ddffcf3f98ace941fa9ed639e7cb7287ea5d291f0433f4ed8f360f5e7c305507e02853e4c
@@ -1,4 +1,10 @@
1
- # Changelog
1
+ # Changelog
2
+
3
+ ## 1.6.8
4
+
5
+ Feature:
6
+
7
+ - A refactoring to allow users to chose to use ActiveModel validation instead of the custom ActiveModel-like validation built in to Flexirest. In a future release this will become the default. (thanks to KARASZI István for the pull request)
2
8
 
3
9
  ## 1.6.7
4
10
 
@@ -78,91 +84,91 @@ Feature:
78
84
 
79
85
  - Changing `_request` to accept options, including `:headers`, rather than headers directly
80
86
 
81
- ## 1.5.3
87
+ ## 1.5.3
82
88
 
83
89
  Feature:
84
90
 
85
91
  - Allow passing custom headers as an option to raw requests.
86
92
 
87
- ## 1.5.2
93
+ ## 1.5.2
88
94
 
89
95
  Bugfix:
90
96
 
91
97
  - Some APIs return an empty response body even on 200s, so any valid status with an empty body should be handled nicely
92
98
 
93
- ## 1.5.1
99
+ ## 1.5.1
94
100
 
95
101
  Bugfix:
96
102
 
97
103
  - PUT/POST/PATCH methods called on an instantiated object should merge the objects attributes with specified params.
98
104
 
99
- ## 1.5.0
105
+ ## 1.5.0
100
106
 
101
107
  Bugfix:
102
108
 
103
109
  - GET requests with the same URL as PUT requests shouldn't use the etag cached version.
104
110
 
105
- ## 1.4.8/1.4.9
111
+ ## 1.4.8/1.4.9
106
112
 
107
113
  Bugfix:
108
114
 
109
115
  - Responses without content (202, 204) will return an empty object.
110
116
 
111
- ## 1.4.7
117
+ ## 1.4.7
112
118
 
113
119
  Bugfix:
114
120
 
115
121
  - Responses without content (202, 204) will still make the headers available in `_headers`.
116
122
 
117
- ## 1.4.6
123
+ ## 1.4.6
118
124
 
119
125
  Feature:
120
126
 
121
127
  - You can define how to handle the body of `delete` requests now with the mapping option `send_delete_body`.
122
128
 
123
- ## 1.4.5
129
+ ## 1.4.5
124
130
 
125
131
  Bugfix:
126
132
 
127
133
  - DELETE requests shouldn't send a request body, the body semantics are undefined.
128
134
 
129
- ## 1.4.4
135
+ ## 1.4.4
130
136
 
131
137
  Feature:
132
138
 
133
139
  - Handling 202s without any content the same as a 204.
134
140
 
135
- ## 1.4.3
141
+ ## 1.4.3
136
142
 
137
143
  Feature:
138
144
 
139
145
  - Added more client exceptions to allow fine grained exception trapping
140
146
 
141
- ## 1.4.2
147
+ ## 1.4.2
142
148
 
143
149
  Bugfix:
144
150
 
145
151
  - Breakage in path parameters where the value isn't specified
146
152
 
147
- ## 1.4.1
153
+ ## 1.4.1
148
154
 
149
155
  Bugfix:
150
156
 
151
157
  - Pluses in URL params are now escaped to %2B (thanks to jan-vitek for the bug report and pull request)
152
158
 
153
- ## 1.4.0
159
+ ## 1.4.0
154
160
 
155
161
  Feature:
156
162
 
157
163
  - New JSON API support - thanks to Mike Voets for all his hard work!
158
164
 
159
- ## 1.3.35
165
+ ## 1.3.35
160
166
 
161
167
  Bugfix:
162
168
 
163
169
  - Slashes in URL params are now escaped to %2F (thanks to davidtolsma for the bug report)
164
170
 
165
- ## 1.3.34
171
+ ## 1.3.34
166
172
 
167
173
  Feature:
168
174
 
@@ -172,187 +178,187 @@ Bugfix:
172
178
 
173
179
  - Now can disable caching on subclasses after being enabled on a parent (thanks to yujideveloper for the PR)
174
180
 
175
- ## 1.3.33
181
+ ## 1.3.33
176
182
 
177
183
  Feature:
178
184
 
179
185
  - Allowed specifying custom message for validation failures
180
186
 
181
- ## 1.3.32
187
+ ## 1.3.32
182
188
 
183
189
  Bugfix:
184
190
 
185
191
  - Rolled back 1.3.31 - was an error in client code
186
192
 
187
- ## 1.3.31
193
+ ## 1.3.31
188
194
 
189
195
  Bugfix:
190
196
 
191
197
  - Working with later versions of Faraday where the response seems to have lost response_headers
192
198
 
193
- ## 1.3.30
199
+ ## 1.3.30
194
200
 
195
201
  Bugfix:
196
202
 
197
203
  - Restoring cached Flexirest::ResultIterators created via a Proxy wasn't restoring correctly
198
204
 
199
- ## 1.3.29
205
+ ## 1.3.29
200
206
 
201
207
  Bugfix:
202
208
 
203
209
  - Setting `perform_caching` on `Flexirest::Base` was being ignored
204
210
 
205
- ## 1.3.28
211
+ ## 1.3.28
206
212
 
207
213
  Feature:
208
214
 
209
215
  - Implemented delete_if on ResultIterator
210
216
 
211
- ## 1.3.27
217
+ ## 1.3.27
212
218
 
213
219
  Bugfix:
214
220
 
215
221
  - HTTP GET requests shouldn't send any body, JSON-encoded or otherwise
216
222
 
217
- ## 1.3.26
223
+ ## 1.3.26
218
224
 
219
225
  Bugfix:
220
226
 
221
227
  - Parameters sent within the URL (e.g. /foo/:bar) should be URI escaped or Flexirest raises an error about unparseable URLs
222
228
 
223
- ## 1.3.25
229
+ ## 1.3.25
224
230
 
225
231
  Feature:
226
232
 
227
233
  - Improvements in performance due to date parsing (thanks to guanglunw for the PR)
228
234
 
229
- ## 1.3.24
235
+ ## 1.3.24
230
236
 
231
237
  Bugfix:
232
238
 
233
239
  - Calling class methods on an instance where the instance is cacheable should work (thanks to johnmckinght for the bug report)
234
240
 
235
- ## 1.3.23
241
+ ## 1.3.23
236
242
 
237
243
  Bugfix:
238
244
 
239
245
  - Should not parse multiline strings as `DateTime` when using the automatica parsing (thanks to execjosh for the PR)
240
246
 
241
- ## 1.3.22
247
+ ## 1.3.22
242
248
 
243
249
  Bugfix:
244
250
 
245
251
  - Broke a test in v1.3.21 (according to Travis) which was passing locally, updated all my gems and then it broke locally, so reverted the test.
246
252
 
247
- ## 1.3.21
253
+ ## 1.3.21
248
254
 
249
255
  Feature:
250
256
 
251
257
  - Now any requests returning a 204 with an empty (nil or blank) body return true instead of raising a ParseException
252
258
 
253
- ## 1.3.20
259
+ ## 1.3.20
254
260
 
255
261
  Bugfix:
256
262
 
257
263
  - Fixed `has_one` association raising an error if there is no associated object (it should just return `nil`) (thanks to Azat Galikhanov for the PR)
258
264
 
259
- ## 1.3.19
265
+ ## 1.3.19
260
266
 
261
267
  Feature:
262
268
 
263
269
  - Added Headers in to Flexirest::ResponseParseException to aid debugging of why it doesn't work against custom APIs.
264
270
 
265
- ## 1.3.18
271
+ ## 1.3.18
266
272
 
267
273
  Feature:
268
274
 
269
275
  - Simplistic load balancing of API servers by supplying an array of URLs to `base_url`. It then pulls a random one out for each request.
270
276
 
271
- ## 1.3.17
277
+ ## 1.3.17
272
278
 
273
279
  Bugfix:
274
280
 
275
281
  - Authentication credentials weren't being passed through proxied classes (thanks to Lukasz Modlinski for the contribution).
276
282
 
277
- ## 1.3.16
283
+ ## 1.3.16
278
284
 
279
285
  Feature:
280
286
 
281
287
  - Allows disabling of the automatic date parsing with the `Flexirest::Base.disable_automatic_date_parsing` setting and/or specifying it per mapped method with the `:parse_fields` option (thanks to Michael Mealling for the request).
282
288
 
283
- ## 1.3.15
289
+ ## 1.3.15
284
290
 
285
291
  Feature:
286
292
 
287
293
  - Allows setting of the ApiAuth `:digest` or `:override_http_method` if v2.0 or above of ApiAuth is installed (thanks to Alan Ruth for the request).
288
294
 
289
- ## 1.3.14
295
+ ## 1.3.14
290
296
 
291
297
  Feature:
292
298
 
293
299
  - Plain Requests (both using the `plain: true` option to mapped methods and using `_plain_request`) return a `Flexirest::PlainResponse` which is string-like for all intents and purposes (it's comparable with strings using the body of the response) and also has `_status` and `_headers` methods (thanks to Rui Ribeiro for the request/inspiration).
294
300
 
295
- ## 1.3.13
301
+ ## 1.3.13
296
302
 
297
303
  Feature:
298
304
 
299
305
  - The undocumented `plain: true` option to mapped methods was tested and documented.
300
306
 
301
- ## 1.3.12
307
+ ## 1.3.12
302
308
 
303
309
  Bugfix:
304
310
 
305
311
  - The Travis build was breaking because Guard pulls in Listen, which only runs on Ruby 2.2 and above. So I removed Guard so the gem can be tested to work against older Ruby versions still.
306
312
 
307
- ## 1.3.11
313
+ ## 1.3.11
308
314
 
309
315
  Feature:
310
316
 
311
317
  - Made the `Flexirest::*Exception#message` much nicer to help debugging applications, e.g. `Sending PUT to '/enable' returned a 500 with the body of - {"error":"John doesn't exist", "code":1234}`.
312
318
 
313
- ## 1.3.10
319
+ ## 1.3.10
314
320
 
315
321
  Feature:
316
322
 
317
323
  - Added per-request params encoding so you can choose between `param[]=foo&param[]=bar` or `param=foo&param=bar` (thanks to bkubic for the PR).
318
324
 
319
- ## 1.3.9
325
+ ## 1.3.9
320
326
 
321
327
  Feature:
322
328
 
323
329
  - Proxying now works for PATCH requests, along with the existing GET, POST, PUT and DELETE (thanks to Andrew Schaper for the PR).
324
330
 
325
- ## 1.3.8
331
+ ## 1.3.8
326
332
 
327
333
  Bugfix:
328
334
 
329
335
  - Fixing crash when trying to parse a JSON response body for error codes and no translator present.
330
336
 
331
- ## 1.3.7
337
+ ## 1.3.7
332
338
 
333
339
  Bugfix:
334
340
 
335
341
  - Removed some more warnings about using uninitialized variables (thanks to Joel Low for the heads-up).
336
342
 
337
- ## 1.3.6
343
+ ## 1.3.6
338
344
 
339
345
  Bugfix:
340
346
 
341
347
  - Removed some warnings about using uninitialized variables (thanks to Joel Low for the heads-up).
342
348
 
343
- ## 1.3.5
349
+ ## 1.3.5
344
350
 
345
351
  Bugfix:
346
352
 
347
353
  - Deeply nested has_many relationships weren't working (thanks to Lewis Buckley for the bug report, spec and fix).
348
354
 
349
- ## 1.3.4
355
+ ## 1.3.4
350
356
 
351
357
  Features:
352
358
 
353
359
  - Allows assigning `STDOUT` to `Flexirest::Logger.logfile` which can be useful when debugging Flexirest or applications at the console (either `rails console` from a Rails app or `rake console` from within Flexirest's codebase) along with setting `verbose!` on the class.
354
360
 
355
- ## 1.3.3
361
+ ## 1.3.3
356
362
 
357
363
  Features:
358
364
 
@@ -504,7 +510,7 @@ Bugfixes
504
510
  - Start of XML support
505
511
  - URL encoding username and password
506
512
 
507
- ## 1.0.9
513
+ ## 1.0.9
508
514
 
509
515
  Bugfixes
510
516
 
data/README.md CHANGED
File without changes
@@ -1,6 +1,6 @@
1
1
  # *Flexirest:* Validation
2
2
 
3
- You can create validations on your objects just like Rails' built in ActiveModel validations. For example:
3
+ Flexirest comes with its own validation. It is very similar to the Rails' built in ActiveModel validations. For example:
4
4
 
5
5
  ```ruby
6
6
  class Person < Flexirest::Base
@@ -20,6 +20,7 @@ class Person < Flexirest::Base
20
20
  end
21
21
  ```
22
22
 
23
+
23
24
  Note: the block based validation is responsible for adding errors to `object._errors[name]` (and this will automatically be ready for `<<` inserting into).
24
25
 
25
26
  Validations are run when calling `valid?` or when calling any API on an instance (and then only if it is `valid?` will the API go on to be called).
@@ -83,6 +84,34 @@ The following attributes will pass validation since they explicitly `allow_nil`:
83
84
  - `:retirement_age`
84
85
  - `:favorite_authors`
85
86
 
87
+ ## ActiveModel::Validations
88
+
89
+ This built-in validations have a bit different syntax than the ActiveModel validations and use a different codebase.
90
+
91
+ You can opt-out from the built-in validations and use the `ActiveModel` validations instead if you inherit from the `Flexirest::BaseWithoutValidation` class instead of the `Flexirest::Base`.
92
+
93
+ Here is the same example what you could see at the top but with `ActiveModel` validations:
94
+
95
+
96
+ ```ruby
97
+ class Person < Flexirest::BaseWithoutValidation
98
+ include ActiveModel::Validations
99
+
100
+ validates :first_name, :last_name, presence: true # ensures that the value is present and not blank
101
+ validates :password, length: { within: 6..12, message: "Invalid password length, must be 6-12 characters" }
102
+ validates :post_code, length: { minimum: 6, maximum: 8 }
103
+ validates :salary, numericality: { greater_than_or_equal_to: 20_000, less_than_or_equal_to: 50_000 }
104
+ validates :age, numericality: { greater_than_or_equal_to: 18, less_than_or_equal_to: 65 }
105
+ validates :suffix, inclusion: { in: %w{Dr. Mr. Mrs. Ms.} }
106
+
107
+ validate do
108
+ errors.add(:name, "must be over 4 chars long") if first_name.length <= 4
109
+ end
110
+
111
+ get :index, '/'
112
+ end
113
+ ```
114
+
86
115
 
87
116
  -----
88
117
 
@@ -34,6 +34,7 @@ Gem::Specification.new do |spec|
34
34
  spec.add_development_dependency 'coveralls'
35
35
  spec.add_development_dependency "api-auth", ">= 1.3.1"
36
36
  spec.add_development_dependency 'typhoeus'
37
+ spec.add_development_dependency 'activemodel'
37
38
 
38
39
  spec.add_runtime_dependency "multi_json"
39
40
  spec.add_runtime_dependency "crack"
@@ -20,6 +20,7 @@ require "flexirest/validation"
20
20
  require "flexirest/callbacks"
21
21
  require "flexirest/proxy_base"
22
22
  require "flexirest/recording"
23
+ require "flexirest/base_without_validation"
23
24
  require "flexirest/base"
24
25
  require "flexirest/monkey_patching"
25
26
  require "flexirest/plain_response"
@@ -33,4 +34,8 @@ module Flexirest
33
34
  def self.name=(value)
34
35
  @@name = value
35
36
  end
37
+
38
+ class NoAttributeException < StandardError ; end
39
+ class ValidationFailedException < StandardError ; end
40
+ class MissingOptionalLibraryError < StandardError ; end
36
41
  end
@@ -1,228 +1,14 @@
1
1
  module Flexirest
2
- class Base
3
- include Mapping
4
- include Configuration
5
- include Callbacks
2
+ class Base < BaseWithoutValidation
6
3
  include Validation
7
- include Caching
8
- include Recording
9
- include AttributeParsing
10
- include Associations
11
-
12
- attr_accessor :_status
13
- attr_accessor :_etag
14
- attr_accessor :_headers
15
-
16
- instance_methods.each do |m|
17
- next unless %w{display presence load require hash untrust trust freeze method enable_warnings with_warnings suppress capture silence quietly debugger breakpoint}.map(&:to_sym).include? m
18
- undef_method m
19
- end
20
4
 
21
5
  def initialize(attrs={})
22
- @attributes = {}
23
- @dirty_attributes = Hash.new
24
-
25
- raise Exception.new("Cannot instantiate Base class") if self.class.name == "Flexirest::Base"
26
-
27
- attrs.each do |attribute_name, attribute_value|
28
- attribute_name = attribute_name.to_sym
29
- @attributes[attribute_name] = parse_date?(attribute_name) ? parse_attribute_value(attribute_value) : attribute_value
30
- @dirty_attributes[attribute_name] = [nil, attribute_value]
31
- end
32
- end
33
-
34
- def _clean!
35
- @dirty_attributes = Hash.new
36
- end
37
-
38
- def _attributes
39
- @attributes
40
- end
41
-
42
- def _copy_from(result)
43
- @attributes = result._attributes
44
- @_status = result._status
45
- end
46
-
47
- def dirty?
48
- @dirty_attributes.size > 0
49
- end
50
-
51
- def changed?
52
- dirty?
53
- end
54
-
55
- # Returns an array of changed fields
56
- def changed
57
- @dirty_attributes.keys
58
- end
59
-
60
- # Returns hash of old and new vaules for each changed field
61
- def changes
62
- @dirty_attributes
6
+ raise Exception.new("Cannot instantiate Base class") if self.class == Flexirest::Base
7
+ super
63
8
  end
64
9
 
65
10
  def errors
66
11
  @attributes[:errors] || (_errors != {} ? _errors : nil)
67
12
  end
68
-
69
- def self._request(request, method = :get, params = nil, options = {})
70
- prepare_direct_request(request, method, options).call(params)
71
- end
72
-
73
- def self._plain_request(request, method = :get, params = nil, options = {})
74
- prepare_direct_request(request, method, options.merge(plain:true)).call(params)
75
- end
76
-
77
- def self._lazy_request(request, method = :get, params = nil, options = {})
78
- Flexirest::LazyLoader.new(prepare_direct_request(request, method, options), params)
79
- end
80
-
81
- def self.prepare_direct_request(request, method = :get, options={})
82
- unless request.is_a? Flexirest::Request
83
- options[:plain] ||= false
84
- options[:direct] ||= true
85
- request = Flexirest::Request.new({ url: request, method: method, options: options }, self)
86
- end
87
- request
88
- end
89
-
90
- def self._request_for(method_name, *args)
91
- if mapped = self._mapped_method(method_name)
92
- params = (args.first.is_a?(Hash) ? args.first : nil)
93
- request = Request.new(mapped, self, params)
94
- request
95
- else
96
- nil
97
- end
98
- end
99
-
100
- def [](key)
101
- @attributes[key.to_sym]
102
- end
103
-
104
- def []=(key, value)
105
- _set_attribute(key, value)
106
- end
107
-
108
- def each
109
- @attributes.each do |key, value|
110
- yield key, value
111
- end
112
- end
113
-
114
- def inspect
115
- inspection = if @attributes.any?
116
- @attributes.collect { |key, value|
117
- "#{key}: #{value_for_inspect(value)}"
118
- }.compact.join(", ")
119
- else
120
- "[uninitialized]"
121
- end
122
- inspection += "#{"," if @attributes.any?} ETag: #{@_etag}" unless @_etag.nil?
123
- inspection += "#{"," if @attributes.any?} Status: #{@_status}" unless @_status.nil?
124
- inspection += " (unsaved: #{@dirty_attributes.keys.map(&:to_s).join(", ")})" if @dirty_attributes.any?
125
- "#<#{self.class} #{inspection}>"
126
- end
127
-
128
- def method_missing(name, *args)
129
- if name.to_s[-1,1] == "="
130
- name = name.to_s.chop.to_sym
131
- _set_attribute(name, args.first)
132
- else
133
- name_sym = name.to_sym
134
- name = name.to_s
135
-
136
- if @attributes.has_key? name_sym
137
- @attributes[name_sym]
138
- else
139
- if name[/^lazy_/] && mapped = self.class._mapped_method(name_sym)
140
- if mapped[:method] != :delete
141
- raise ValidationFailedException.new unless valid?
142
- end
143
-
144
- request = Request.new(mapped, self, args.first)
145
- Flexirest::LazyLoader.new(request)
146
- elsif mapped = self.class._mapped_method(name_sym)
147
- if mapped[:method] != :delete
148
- raise ValidationFailedException.new unless valid?
149
- end
150
-
151
- request = Request.new(mapped, self, args.first)
152
- request.call
153
- elsif name[/_was$/] and @attributes.has_key? (name.sub(/_was$/,'').to_sym)
154
- k = (name.sub(/_was$/,'').to_sym)
155
- @dirty_attributes[k][0]
156
- elsif name[/^reset_.*!$/] and @attributes.has_key? (name.sub(/^reset_/,'').sub(/!$/,'').to_sym)
157
- k = (name.sub(/^reset_/,'').sub(/!$/,'').to_sym)
158
- _reset_attribute(k)
159
- elsif self.class.whiny_missing
160
- raise NoAttributeException.new("Missing attribute #{name_sym}")
161
- else
162
- nil
163
- end
164
- end
165
- end
166
- end
167
-
168
- def respond_to_missing?(method_name, include_private = false)
169
- @attributes.has_key? method_name.to_sym
170
- end
171
-
172
- def to_hash
173
- output = {}
174
- @attributes.each do |key, value|
175
- if value.is_a? Flexirest::Base
176
- output[key.to_s] = value.to_hash
177
- elsif value.is_a? Array
178
- output[key.to_s] = value.map(&:to_hash)
179
- else
180
- output[key.to_s] = value
181
- end
182
- end
183
- output
184
- end
185
-
186
- def to_json
187
- output = to_hash
188
- output.to_json
189
- end
190
-
191
- private
192
-
193
- def _set_attribute(key, value)
194
- old_value = @dirty_attributes[key.to_sym]
195
- old_value = @attributes[key.to_sym] unless old_value
196
- old_value = old_value[0] if old_value and old_value.is_a? Array
197
- @dirty_attributes[key.to_sym] = [old_value, value]
198
- @attributes[key.to_sym] = value
199
- end
200
-
201
- def _reset_attribute(key)
202
- old_value = @dirty_attributes[key.to_sym]
203
- @attributes[key.to_sym] = old_value[0] if old_value and old_value.is_a? Array
204
- @dirty_attributes.delete(key.to_sym)
205
- end
206
-
207
- def value_for_inspect(value)
208
- if value.is_a?(String) && value.length > 50
209
- "#{value[0..50]}...".inspect
210
- elsif value.is_a?(Date) || value.is_a?(Time)
211
- %("#{value.to_s(:db)}")
212
- else
213
- value.inspect
214
- end
215
- end
216
-
217
- def parse_date?(name)
218
- return true if self.class._date_fields.include?(name)
219
- return true if !Flexirest::Base.disable_automatic_date_parsing && self.class._date_fields.empty?
220
- false
221
- end
222
-
223
13
  end
224
-
225
- class NoAttributeException < StandardError ; end
226
- class ValidationFailedException < StandardError ; end
227
- class MissingOptionalLibraryError < StandardError ; end
228
14
  end