flexirest 1.2.17 → 1.2.18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +76 -0
- data/lib/flexirest/request.rb +8 -3
- data/lib/flexirest/validation.rb +43 -22
- data/lib/flexirest/version.rb +1 -1
- data/spec/lib/request_spec.rb +16 -0
- data/spec/lib/validation_spec.rb +70 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 951a773aca32f3710bae2ee3ed2f4a34c4ee9232
|
4
|
+
data.tar.gz: d0857284056ec1f1c6b563e1d67f92c8fcae81bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 29904f4d2b02428fbb1d056667c3ade2bf42cae9f859e4f328c4cd3ebde47a57160f6c8df00fab0f4967e23cc734bbd26f27e54714b6ebbdb4b46a53986f92fa
|
7
|
+
data.tar.gz: bf945048697c7dc7aa235cc4ef4fffe6a5d6260731d806395f413b797f05e95aa4b1d5f1ab9d1b58f02880bf5c53dd3ca5a14bf4dda1a0673eba34d7c4eac522
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -176,6 +176,34 @@ puts @person.expenses.reduce {|e| e.inc_vat}
|
|
176
176
|
puts @person.address.full_string
|
177
177
|
```
|
178
178
|
|
179
|
+
Sometimes we want attributes to just return a simple Ruby Array. To achieve this we can add an `:array` option to the method. This is especially useful when the attribute contains an array of scalar values. If you don't specify the `:array` option Flexirest will return a `Flexirest::ResultIterator`. To illustrate the difference consider the following example:
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
class Book < Flexirest::Base
|
183
|
+
# :authors attribute ["Robert T. Kiyosaki", "Sharon L. Lechter C.P.A"]
|
184
|
+
# :genres attribute ["self-help", "finance", "education"]
|
185
|
+
get :find, "/books/:name", array: [:authors]
|
186
|
+
end
|
187
|
+
```
|
188
|
+
|
189
|
+
In the example above, the following results can be observed:
|
190
|
+
|
191
|
+
```ruby
|
192
|
+
@book = Book.find("rich-dad-poor-dad")
|
193
|
+
puts @book.authors
|
194
|
+
#=> ["Robert T. Kiyosaki", "Sharon L. Lechter C.P.A"]
|
195
|
+
puts @book.authors.class
|
196
|
+
#=> Array
|
197
|
+
puts @book.genres
|
198
|
+
#=> #<Flexirest::ResultIterator:0x007ff420fe7a88 @_status=nil, @_headers=nil, @items=["self-help", "finance", "education"]>
|
199
|
+
puts @books.genres.class
|
200
|
+
#=> Flexirest::ResultIterator
|
201
|
+
puts @books.genres.items
|
202
|
+
#=> ["self-help", "finance", "education"]
|
203
|
+
```
|
204
|
+
|
205
|
+
When the `:array` option includes an attribute, it is assumed the values were returned with the request, and they will not be lazily loaded. It is also assumed the attribute values do not map to a Flexirest resource.
|
206
|
+
|
179
207
|
#### Association Type 2 - Lazy Loading From Other URLs
|
180
208
|
|
181
209
|
When mapping the method, passing a list of attributes will cause any requests for those attributes to mapped to the URLs given in their responses. The response for the attribute may be one of the following:
|
@@ -773,6 +801,54 @@ Validations are run when calling `valid?` or when calling any API on an instance
|
|
773
801
|
|
774
802
|
`full_error_messages` returns an array of attributes with their associated error messages, i.e. `["age must be at least 18"]`
|
775
803
|
|
804
|
+
#### Permitting nil values
|
805
|
+
The default behavior for `:length`, `:numericality` and `:inclusion` validators is to fail when a `nil` value is encountered. You can prevent `nil` attribute values from triggering validation errors for attributes that may permit `nil` by adding the `:allow_nil => true` option. Adding this option with a `true` value to `:length`, `:numericality` and `:inclusion` validators will permit `nil` values and not trigger errors. Some examples are:
|
806
|
+
|
807
|
+
```ruby
|
808
|
+
class Person < Flexirest::Base
|
809
|
+
validates :first_name, presence: true
|
810
|
+
validates :middle_name, length: { minimum: 2, maximum: 30 }, allow_nil: true
|
811
|
+
validates :last_name, existence: true
|
812
|
+
validates :nick_name, length: { minimum: 2, maximum: 30 }
|
813
|
+
validates :alias, length: { minimum: 2, maximum: 30 }, allow_nil: false
|
814
|
+
validates :password, length: { within: 6..12 }
|
815
|
+
validates :post_code, length: { minimum: 6, maximum: 8 }
|
816
|
+
validates :salary, numericality: true, minimum: 20_000, maximum: 50_000
|
817
|
+
validates :age, numericality: { minimum: 18, maximum: 65 }
|
818
|
+
validates :suffix, inclusion: { in: %w{Dr. Mr. Mrs. Ms.}}
|
819
|
+
validates :golf_score, numericality: true, allow_nil: true
|
820
|
+
validates :retirement_age, numericality: { minimum: 65 }, allow_nil: true
|
821
|
+
validates :cars_owned, numericality: true
|
822
|
+
validates :houses_owned, numericality: true, allow_nil: false
|
823
|
+
validates :favorite_authors, inclusion: { in: ["George S. Klason", "Robert T. Kiyosaki", "Lee Child"] }, allow_nil: true
|
824
|
+
validates :favorite_artists, inclusion: { in: ["Claude Monet", "Vincent Van Gogh", "Andy Warhol"] }
|
825
|
+
validates :favorite_composers, inclusion: { in: ["Mozart", "Bach", "Pachelbel", "Beethoven"] }, allow_nil: false
|
826
|
+
end
|
827
|
+
```
|
828
|
+
|
829
|
+
In the example above, the following results would occur when calling `valid?` on an instance where all attributes have `nil` values:
|
830
|
+
|
831
|
+
- `:first_name` must be present
|
832
|
+
- `:last_name` must be not be nil
|
833
|
+
- `:nick_name` must be not be nil
|
834
|
+
- `:alias` must not be nil
|
835
|
+
- `:password` must not be nil
|
836
|
+
- `:post_code` must not be nil
|
837
|
+
- `:salary` must not be nil
|
838
|
+
- `:age` must not be nil
|
839
|
+
- `:suffix` must not be nil
|
840
|
+
- `:cars_owned` must not be nil
|
841
|
+
- `:houses_owned` must not be nil
|
842
|
+
- `:favorite_artists` must not be nil
|
843
|
+
- `:favorite_composers` must not be nil
|
844
|
+
|
845
|
+
The following attributes will pass validation since they explicitly `allow_nil`:
|
846
|
+
|
847
|
+
- `:middle_name`
|
848
|
+
- `:golf_score`
|
849
|
+
- `:retirement_age`
|
850
|
+
- `:favorite_authors`
|
851
|
+
|
776
852
|
### Debugging
|
777
853
|
|
778
854
|
You can turn on verbose debugging to see what is sent to the API server and what is returned in one of these two ways:
|
data/lib/flexirest/request.rb
CHANGED
@@ -13,8 +13,9 @@ module Flexirest
|
|
13
13
|
@method = method
|
14
14
|
@method[:options] ||= {}
|
15
15
|
@method[:options][:lazy] ||= []
|
16
|
+
@method[:options][:array] ||= []
|
16
17
|
@method[:options][:has_one] ||= {}
|
17
|
-
@overridden_name
|
18
|
+
@overridden_name = @method[:options][:overridden_name]
|
18
19
|
@object = object
|
19
20
|
@response_delegate = Flexirest::RequestDelegator.new(nil)
|
20
21
|
@params = params
|
@@ -440,7 +441,11 @@ module Flexirest
|
|
440
441
|
elsif v.is_a? Hash
|
441
442
|
object._attributes[k] = new_object(v, overridden_name )
|
442
443
|
elsif v.is_a? Array
|
443
|
-
|
444
|
+
if @method[:options][:array].include?(k)
|
445
|
+
object._attributes[k] = Array.new
|
446
|
+
else
|
447
|
+
object._attributes[k] = Flexirest::ResultIterator.new
|
448
|
+
end
|
444
449
|
v.each do |item|
|
445
450
|
if item.is_a? Hash
|
446
451
|
object._attributes[k] << new_object(item, overridden_name)
|
@@ -514,7 +519,7 @@ module Flexirest
|
|
514
519
|
if @method[:options][:has_many][name] || @method[:options][:has_one][name]
|
515
520
|
return name
|
516
521
|
end
|
517
|
-
|
522
|
+
|
518
523
|
parent_name || name
|
519
524
|
end
|
520
525
|
|
data/lib/flexirest/validation.rb
CHANGED
@@ -20,6 +20,7 @@ module Flexirest
|
|
20
20
|
@errors = Hash.new {|h,k| h[k] = []}
|
21
21
|
self.class._validations.each do |validation|
|
22
22
|
value = self.send(validation[:field_name])
|
23
|
+
allow_nil = validation[:options].fetch(:allow_nil, false)
|
23
24
|
validation[:options].each do |type, options|
|
24
25
|
if type == :presence
|
25
26
|
if value.nil?
|
@@ -32,35 +33,55 @@ module Flexirest
|
|
32
33
|
@errors[validation[:field_name]] << "must be not be nil"
|
33
34
|
end
|
34
35
|
elsif type == :length
|
35
|
-
if
|
36
|
-
@errors[validation[:field_name]] << "must be
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
36
|
+
if value.nil?
|
37
|
+
@errors[validation[:field_name]] << "must be not be nil" unless allow_nil
|
38
|
+
else
|
39
|
+
if options[:within]
|
40
|
+
@errors[validation[:field_name]] << "must be within range #{options[:within]}" unless options[:within].include?(value.to_s.length )
|
41
|
+
end
|
42
|
+
if options[:minimum]
|
43
|
+
@errors[validation[:field_name]] << "must be at least #{options[:minimum]} characters long" unless value.to_s.length >= options[:minimum]
|
44
|
+
end
|
45
|
+
if options[:maximum]
|
46
|
+
@errors[validation[:field_name]] << "must be no more than #{options[:maximum]} characters long" unless value.to_s.length <= options[:maximum]
|
47
|
+
end
|
43
48
|
end
|
44
49
|
elsif type == :numericality
|
45
|
-
|
46
|
-
|
47
|
-
@errors[validation[:field_name]] << "must be numeric"
|
50
|
+
if value.nil?
|
51
|
+
@errors[validation[:field_name]] << "must be not be nil" unless allow_nil
|
48
52
|
else
|
49
|
-
if
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
if options
|
54
|
-
|
53
|
+
numeric = (true if Float(value) rescue false)
|
54
|
+
if !numeric
|
55
|
+
@errors[validation[:field_name]] << "must be numeric"
|
56
|
+
else
|
57
|
+
if options.is_a?(Hash)
|
58
|
+
if options[:minimum]
|
59
|
+
@errors[validation[:field_name]] << "must be at least #{options[:minimum]}" unless value.to_f >= options[:minimum]
|
60
|
+
end
|
61
|
+
if options[:maximum]
|
62
|
+
@errors[validation[:field_name]] << "must be no more than #{options[:maximum]}" unless value.to_f <= options[:maximum]
|
63
|
+
end
|
55
64
|
end
|
56
65
|
end
|
57
66
|
end
|
58
|
-
elsif type == :minimum
|
59
|
-
|
60
|
-
|
61
|
-
|
67
|
+
elsif type == :minimum
|
68
|
+
if value.nil?
|
69
|
+
@errors[validation[:field_name]] << "must be not be nil" unless allow_nil
|
70
|
+
else
|
71
|
+
@errors[validation[:field_name]] << "must be at least #{options}" unless value.to_f >= options.to_f
|
72
|
+
end
|
73
|
+
elsif type == :maximum
|
74
|
+
if value.nil?
|
75
|
+
@errors[validation[:field_name]] << "must be not be nil" unless allow_nil
|
76
|
+
else
|
77
|
+
@errors[validation[:field_name]] << "must be no more than #{options}" unless value.to_f <= options.to_f
|
78
|
+
end
|
62
79
|
elsif type == :inclusion
|
63
|
-
|
80
|
+
if value.nil?
|
81
|
+
@errors[validation[:field_name]] << "must be not be nil" unless allow_nil
|
82
|
+
else
|
83
|
+
@errors[validation[:field_name]] << "must be included in #{options[:in].join(", ")}" unless options[:in].include?(value)
|
84
|
+
end
|
64
85
|
end
|
65
86
|
end
|
66
87
|
if validation[:block]
|
data/lib/flexirest/version.rb
CHANGED
data/spec/lib/request_spec.rb
CHANGED
@@ -22,6 +22,7 @@ describe Flexirest::Request do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
get :all, "/", :has_many => {:expenses => ExampleOtherClient}
|
25
|
+
get :array, "/johnny", array: [:likes, :dislikes]
|
25
26
|
get :babies, "/babies", :has_many => {:children => ExampleOtherClient}
|
26
27
|
get :single_association, "/single", :has_one => {:single => ExampleSingleClient}, :has_many => {:children => ExampleOtherClient}
|
27
28
|
get :headers, "/headers"
|
@@ -261,6 +262,21 @@ describe Flexirest::Request do
|
|
261
262
|
expect(object[1].first_name).to eq("Billy")
|
262
263
|
expect(object._status).to eq(200)
|
263
264
|
end
|
265
|
+
|
266
|
+
it "should parse an attribute to be an array if attribute included in array option" do
|
267
|
+
expect_any_instance_of(Flexirest::Connection).to receive(:get).with("/johnny", an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(body:"{\"first_name\":\"Johnny\", \"likes\":[\"donuts\", \"bacon\"], \"dislikes\":[\"politicians\", \"lawyers\", \"taxes\"]}", status:200, response_headers:{})))
|
268
|
+
object = ExampleClient.array
|
269
|
+
expect(object.likes).to be_instance_of(Array)
|
270
|
+
expect(object.likes.size).to eq(2)
|
271
|
+
expect(object.likes[0]).to eq("donuts")
|
272
|
+
expect(object.likes[1]).to eq("bacon")
|
273
|
+
expect(object.dislikes).to be_instance_of(Array)
|
274
|
+
expect(object.dislikes.size).to eq(3)
|
275
|
+
expect(object.dislikes[0]).to eq("politicians")
|
276
|
+
expect(object.dislikes[1]).to eq("lawyers")
|
277
|
+
expect(object.dislikes[2]).to eq("taxes")
|
278
|
+
#TODO
|
279
|
+
end
|
264
280
|
|
265
281
|
it "should instantiate other classes using has_many when required to do so" do
|
266
282
|
expect_any_instance_of(Flexirest::Connection).to receive(:get).with("/", an_instance_of(Hash)).and_return(::FaradayResponseMock.new(OpenStruct.new(body:"{\"first_name\":\"Johnny\", \"expenses\":[{\"amount\":1}, {\"amount\":2}]}", status:200, response_headers:{})))
|
data/spec/lib/validation_spec.rb
CHANGED
@@ -4,20 +4,29 @@ describe "Flexirest::Validation" do
|
|
4
4
|
class SimpleValidationExample < OpenStruct
|
5
5
|
include Flexirest::Validation
|
6
6
|
validates :first_name, presence: true
|
7
|
+
validates :middle_name, length: { minimum: 2, maximum: 30 }, allow_nil: true
|
7
8
|
validates :last_name, existence: true
|
9
|
+
validates :nick_name, length: { minimum: 2, maximum: 30 }
|
10
|
+
validates :alias, length: { minimum: 2, maximum: 30 }, allow_nil: false
|
8
11
|
validates :password, length: { within: 6..12 }
|
9
12
|
validates :post_code, length: { minimum: 6, maximum: 8 }
|
10
13
|
validates :salary, numericality: true, minimum: 20_000, maximum: 50_000
|
11
14
|
validates :age, numericality: { minimum: 18, maximum: 65 }
|
12
15
|
validates :suffix, inclusion: { in: %w{Dr. Mr. Mrs. Ms.}}
|
16
|
+
validates :golf_score, numericality: true, allow_nil: true
|
17
|
+
validates :retirement_age, numericality: { minimum: 65 }, allow_nil: true
|
18
|
+
validates :cars_owned, numericality: true
|
19
|
+
validates :houses_owned, numericality: true, allow_nil: false
|
20
|
+
validates :favorite_authors, inclusion: { in: ["George S. Klason", "Robert T. Kiyosaki", "Lee Child"] }, allow_nil: true
|
21
|
+
validates :favorite_artists, inclusion: { in: ["Claude Monet", "Vincent Van Gogh", "Andy Warhol"] }
|
22
|
+
validates :favorite_composers, inclusion: { in: ["Mozart", "Bach", "Pachelbel", "Beethoven"] }, allow_nil: false
|
13
23
|
end
|
14
24
|
|
15
25
|
it "should be able to register a validation" do
|
16
|
-
expect(SimpleValidationExample._validations.size).to eq(
|
26
|
+
expect(SimpleValidationExample._validations.size).to eq(17)
|
17
27
|
end
|
18
28
|
|
19
29
|
context "when validating presence" do
|
20
|
-
|
21
30
|
it "should be invalid if a required value isn't present" do
|
22
31
|
a = SimpleValidationExample.new
|
23
32
|
a.first_name = nil
|
@@ -107,6 +116,24 @@ describe "Flexirest::Validation" do
|
|
107
116
|
a.valid?
|
108
117
|
expect(a._errors[:post_code].size).to eq(1)
|
109
118
|
end
|
119
|
+
|
120
|
+
it "should be valid if a length is nil and allow_nil option is true" do
|
121
|
+
a = SimpleValidationExample.new
|
122
|
+
a.valid?
|
123
|
+
expect(a._errors[:middle_name]).to be_empty
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should be invalid if a length is nil and allow_nil option is not provided" do
|
127
|
+
a = SimpleValidationExample.new
|
128
|
+
a.valid?
|
129
|
+
expect(a._errors[:nick_name].size).to eq(1)
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should be invalid if a length is nil and allow_nil option is false" do
|
133
|
+
a = SimpleValidationExample.new
|
134
|
+
a.valid?
|
135
|
+
expect(a._errors[:alias].size).to eq(1)
|
136
|
+
end
|
110
137
|
end
|
111
138
|
|
112
139
|
|
@@ -136,6 +163,29 @@ describe "Flexirest::Validation" do
|
|
136
163
|
expect(a._errors[:salary].size).to eq(0)
|
137
164
|
end
|
138
165
|
|
166
|
+
it "should be valid if a value is nil and allow_nil option is true" do
|
167
|
+
a = SimpleValidationExample.new
|
168
|
+
a.valid?
|
169
|
+
expect(a._errors[:golf_score]).to be_empty
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should be valid if a value is nil and allow_nil option is true and a hash of options is passed to numericality" do
|
173
|
+
a = SimpleValidationExample.new
|
174
|
+
a.valid?
|
175
|
+
expect(a._errors[:retirement_age]).to be_empty
|
176
|
+
end
|
177
|
+
|
178
|
+
it "should be invalid if a value is nil and allow_nil option is not provided" do
|
179
|
+
a = SimpleValidationExample.new
|
180
|
+
a.valid?
|
181
|
+
expect(a._errors[:cars_owned].size).to eq(1)
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should be invalid if a value is nil and allow_nil option is false" do
|
185
|
+
a = SimpleValidationExample.new
|
186
|
+
a.valid?
|
187
|
+
expect(a._errors[:houses_owned].size).to eq(1)
|
188
|
+
end
|
139
189
|
end
|
140
190
|
|
141
191
|
context "using the original format with min and max as types" do
|
@@ -162,7 +212,6 @@ describe "Flexirest::Validation" do
|
|
162
212
|
a.valid?
|
163
213
|
expect(a._errors[:age].size).to eq(0)
|
164
214
|
end
|
165
|
-
|
166
215
|
end
|
167
216
|
end
|
168
217
|
|
@@ -178,6 +227,24 @@ describe "Flexirest::Validation" do
|
|
178
227
|
a.valid?
|
179
228
|
expect(a._errors[:suffix].size).to eq(0)
|
180
229
|
end
|
230
|
+
|
231
|
+
it "should be valid if the value is nil and allow_nil option is true" do
|
232
|
+
a = SimpleValidationExample.new
|
233
|
+
a.valid?
|
234
|
+
expect(a._errors[:favorite_authors]).to be_empty
|
235
|
+
end
|
236
|
+
|
237
|
+
it "should be invalid if the value is nil and allow_nil option is not provided" do
|
238
|
+
a = SimpleValidationExample.new
|
239
|
+
a.valid?
|
240
|
+
expect(a._errors[:favorite_artists].size).to eq(1)
|
241
|
+
end
|
242
|
+
|
243
|
+
it "should be invalid if the value is nil and allow_nil option is false" do
|
244
|
+
a = SimpleValidationExample.new
|
245
|
+
a.valid?
|
246
|
+
expect(a._errors[:favorite_composers].size).to eq(1)
|
247
|
+
end
|
181
248
|
end
|
182
249
|
|
183
250
|
context "when passing a block" do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flexirest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.18
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Jeffries
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-02-
|
11
|
+
date: 2016-02-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|