flexirest 1.6.7 → 1.6.8

Sign up to get free protection for your applications and to get access to all the features.
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