organ 0.0.3 → 0.1.0

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: f58028758f74b7ad8fdb144b5be194a4b3f3eba6
4
- data.tar.gz: 7391d92ec6d6165e58edb13b61b8290607577aba
3
+ metadata.gz: e29921771214a10a8ed0f1e36243dc60acf78091
4
+ data.tar.gz: ab43375fcb894100bea0ac235efee79e842f6386
5
5
  SHA512:
6
- metadata.gz: 657be4d73f04bd1c6a5aded0f539b2c37c39466b7f5c9879333680734137a7e7448e439c4bc9e93706b8216aab14cbc2997aca5ce50e1b219b6471f52ae7d3f6
7
- data.tar.gz: e87cd083c328bf9b62cc7ad65304ef35b2a4bbb3b5c183092fbe7b78cf60822e1cf05951648f8e059317d44c0128fdb46fd54b2f3552c1ba51f6cc2a715627fa
6
+ metadata.gz: 3c591d8ca4797ab2b229daa7198d3a95a3155bca235a993637e1f97b4cc2f68eda3bd4bc0098e60cde034ed621d750df658d47ceb83953a1fe86f2492d8a67cf
7
+ data.tar.gz: 88c0dfe1e6472348d5b8025c2f8d17d1fe40c8851f32c2fffe28a241d39743e141a1621439ff308a3d6e5dad36104eec2908ef61013e3966191516154cae67ce
data/README.md CHANGED
@@ -176,6 +176,22 @@ appends a `:greater_than` error to the attribute. Example:
176
176
  validate_range(:age, :min => 18)
177
177
  ```
178
178
 
179
+ ### validation_block
180
+
181
+ This is a helper method that only calls the given block if the form doesn't have
182
+ any errors. This is particularly useful when some of the validations are costly
183
+ to make and unnecessary if the form already has errors.
184
+
185
+ ```ruby
186
+ validate_length(:username, :min => 7)
187
+
188
+ validation_block do # Will only get called if previous validation passed
189
+ validate_uniqueness(:username) do |username|
190
+ User.where(:username => username).empty?
191
+ end
192
+ end
193
+ ```
194
+
179
195
  Extensions
180
196
  ----------
181
197
 
@@ -2,6 +2,6 @@ require_relative "organ/form"
2
2
 
3
3
  module Organ
4
4
 
5
- VERSION = "0.0.3"
5
+ VERSION = "0.1.0"
6
6
 
7
7
  end
@@ -24,11 +24,15 @@ module Organ
24
24
  # Corce the value into true or false.
25
25
  #
26
26
  # @param value [Object]
27
+ # @option options [Regexp] :pattern (nil)
28
+ # Try to match regexp pattern with passed value
29
+ # and cast to Boolean this match.
27
30
  #
28
31
  # @return [Boolean]
29
32
  #
30
33
  # @api semipublic
31
34
  def coerce_boolean(value, options = {})
35
+ value = value =~ options[:pattern] if options.has_key?(:pattern)
32
36
  !!value
33
37
  end
34
38
 
@@ -120,6 +124,9 @@ module Organ
120
124
  #
121
125
  # @param value [Object]
122
126
  # The value to be coerced.
127
+ # @option options [String] :format ("%Y-%m-%d")
128
+ # Allow send format to parse date.
129
+ # See http://ruby-doc.org/stdlib-2.1.1/libdoc/date/rdoc/Date.html#method-i-strftime
123
130
  #
124
131
  # @return [Date, nil]
125
132
  # A Date if the value can be coerced or nil otherwise.
@@ -128,7 +135,7 @@ module Organ
128
135
  def coerce_date(value, options = {})
129
136
  value = coerce_string(value)
130
137
  begin
131
- Date.strptime(value, "%Y-%m-%d")
138
+ Date.strptime(value, options.fetch(:format, "%Y-%m-%d"))
132
139
  rescue ArgumentError
133
140
  nil
134
141
  end
@@ -39,6 +39,15 @@ module Organ
39
39
  errors[attribute_name] << error
40
40
  end
41
41
 
42
+ # Call the given block if there are no errors.
43
+ #
44
+ # @param block [Proc]
45
+ #
46
+ # @api public
47
+ def validation_block(&block)
48
+ block.call if errors.empty?
49
+ end
50
+
42
51
  # Validate the presence of the attribute value. If the value is nil or
43
52
  # false append a :blank error to the attribute.
44
53
  #
@@ -47,14 +56,14 @@ module Organ
47
56
  # @api public
48
57
  def validate_presence(attribute_name)
49
58
  value = send(attribute_name)
50
- if !value || value.to_s.empty?
59
+ unless present?(value)
51
60
  append_error(attribute_name, :blank)
52
61
  end
53
62
  end
54
63
 
55
- # Validate the uniqueness of the attribute value. The uniqueness is
56
- # determined by the block given. If the value is not unique, append the
57
- # :taken error to the attribute.
64
+ # Validate the uniqueness of the attribute value (if present). The
65
+ # uniqueness is determined by the block given. If the value is not unique,
66
+ # append the :taken error to the attribute.
58
67
  #
59
68
  # @param attribute_name [Symbol]
60
69
  # @param block [Proc]
@@ -64,13 +73,13 @@ module Organ
64
73
  # @api public
65
74
  def validate_uniqueness(attribute_name, &block)
66
75
  value = send(attribute_name)
67
- unless block.call(value)
76
+ if present?(value) && !block.call(value)
68
77
  append_error(attribute_name, :taken)
69
78
  end
70
79
  end
71
80
 
72
- # Validate the email format. If the value does not match the email format,
73
- # append the :invalid error to the attribute.
81
+ # Validate the email format (if present). If the value does not match the
82
+ # email format, append the :invalid error to the attribute.
74
83
  #
75
84
  # @param attribute_name [Symbol]
76
85
  #
@@ -79,8 +88,8 @@ module Organ
79
88
  validate_format(attribute_name, EMAIL_FORMAT)
80
89
  end
81
90
 
82
- # Validate the format of the attribute value. If the value does not match
83
- # the regexp given, append :invalid error to the attribute.
91
+ # Validate the format of the attribute value (if present). If the value does
92
+ # not match the regexp given, append :invalid error to the attribute.
84
93
  #
85
94
  # @param attribute_name [Symbol]
86
95
  # @param format [Regexp]
@@ -88,15 +97,15 @@ module Organ
88
97
  # @api public
89
98
  def validate_format(attribute_name, format)
90
99
  value = send(attribute_name)
91
- if value && !(format =~ value)
100
+ if present?(value) && !(format =~ value)
92
101
  append_error(attribute_name, :invalid)
93
102
  end
94
103
  end
95
104
 
96
105
  # Validate the length of a String, Array or any other form attribute which
97
- # responds to #size. If the value is too short, append the :too_short
98
- # error to the attribute. If the value is too long append the :too_long
99
- # error to the attribute.
106
+ # responds to #size (if present). If the value is too short, append the
107
+ # :too_short error to the attribute. If the value is too long append the
108
+ # :too_long error to the attribute.
100
109
  #
101
110
  # @param attribute_name [Symbol]
102
111
  # @option options [Integer, nil] :min (nil)
@@ -108,7 +117,7 @@ module Organ
108
117
  max = options.fetch(:max, nil)
109
118
  value = send(attribute_name)
110
119
 
111
- if value
120
+ if present?(value)
112
121
  length = value.size
113
122
  if min && length < min
114
123
  append_error(attribute_name, :too_short)
@@ -119,9 +128,9 @@ module Organ
119
128
  end
120
129
  end
121
130
 
122
- # Validate the value of the given attribute is included in the list. If
123
- # the value is not included in the list, append the :not_included error to
124
- # the attribute.
131
+ # Validate the value of the given attribute is included in the list (if
132
+ # present). If the value is not included in the list, append the
133
+ # :not_included error to the attribute.
125
134
  #
126
135
  # @param attribute_name [Symbol]
127
136
  # @param attribute_name [Symbol]
@@ -130,14 +139,14 @@ module Organ
130
139
  # @api public
131
140
  def validate_inclusion(attribute_name, list)
132
141
  value = send(attribute_name)
133
- if value && !list.include?(value)
142
+ if present?(value) && !list.include?(value)
134
143
  append_error(attribute_name, :not_included)
135
144
  end
136
145
  end
137
146
 
138
- # Validate the range in which the attribute can be. If the value is less
139
- # than the min a :less_than_min error will be appended. If the value is
140
- # greater than the max a :greater_than_max error will be appended.
147
+ # Validate the range in which the attribute can be (if present). If the
148
+ # value is less than the min a :less_than_min error will be appended. If the
149
+ # value is greater than the max a :greater_than_max error will be appended.
141
150
  #
142
151
  # @param attribute_name [Symbol]
143
152
  # @option options [Integer] :min (nil)
@@ -149,7 +158,7 @@ module Organ
149
158
  def validate_range(attribute_name, options = {})
150
159
  value = send(attribute_name)
151
160
 
152
- return unless value
161
+ return unless present?(value)
153
162
 
154
163
  min = options.fetch(:min, nil)
155
164
  max = options.fetch(:max, nil)
@@ -157,5 +166,16 @@ module Organ
157
166
  append_error(attribute_name, :greater_than) if max && value > max
158
167
  end
159
168
 
169
+ # Determine if the value is present (not nil, false or an empty string).
170
+ #
171
+ # @param value [Object]
172
+ #
173
+ # @return [Boolean]
174
+ #
175
+ # @api private
176
+ def present?(value)
177
+ value && !value.to_s.empty?
178
+ end
179
+
160
180
  end
161
181
  end
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "organ"
3
- s.version = "0.0.3"
3
+ s.version = "0.1.0"
4
4
  s.summary = "Forms with integrated validations and attribute coercing."
5
5
  s.description = "A small library for manipulating form-based data with validations and attributes coercion."
6
6
  s.authors = ["Sebastian Borrazas"]
@@ -50,7 +50,7 @@ describe Organ::Validations do
50
50
 
51
51
  describe "#validate_presence" do
52
52
  describe "when attribute has nil value" do
53
- it "appends an error" do
53
+ it "appends a :blank error" do
54
54
  validator.validate_presence(:username)
55
55
  assert_includes(validator.errors[:username], :blank)
56
56
  assert_equal(1, validator.errors[:username].size)
@@ -60,7 +60,7 @@ describe Organ::Validations do
60
60
  describe "when attribute has empty string value" do
61
61
  let(:username_value) { "" }
62
62
 
63
- it "appends an error" do
63
+ it "appends a :blank error" do
64
64
  validator.validate_presence(:username)
65
65
  assert_includes(validator.errors[:username], :blank)
66
66
  assert_equal(1, validator.errors[:username].size)
@@ -70,46 +70,96 @@ describe Organ::Validations do
70
70
 
71
71
  describe "#validate_uniqueness" do
72
72
  describe "when block returns false" do
73
- it "appends a :taken error" do
74
- validator.validate_uniqueness(:username) { |u| false }
75
- assert_includes(validator.errors[:username], :taken)
76
- assert_equal(1, validator.errors[:username].size)
73
+ describe "when value is not present" do
74
+ let(:username_value) { nil }
75
+
76
+ it "doesn't append any error" do
77
+ validator.validate_uniqueness(:username) { |u| false }
78
+
79
+ assert_equal(0, validator.errors[:username].size)
80
+ end
81
+ end
82
+
83
+ describe "when value is present" do
84
+ let(:username_value) { "username" }
85
+
86
+ it "appends a :taken error" do
87
+ validator.validate_uniqueness(:username) { |u| false }
88
+ assert_includes(validator.errors[:username], :taken)
89
+ assert_equal(1, validator.errors[:username].size)
90
+ end
77
91
  end
78
92
  end
79
93
  end
80
94
 
81
95
  describe "#validate_email_format" do
82
96
  describe "when value is not an email" do
83
- let(:username_value) { "not.an@email" }
97
+ describe "when value is not present" do
98
+ let(:username_value) { nil }
84
99
 
85
- it "appends an :invalid error" do
86
- validator.validate_email_format(:username)
87
- assert_includes(validator.errors[:username], :invalid)
88
- assert_equal(1, validator.errors[:username].size)
100
+ it "doesn't append any error" do
101
+ validator.validate_email_format(:username)
102
+
103
+ assert_equal(0, validator.errors[:username].size)
104
+ end
105
+ end
106
+
107
+ describe "when value is present" do
108
+ let(:username_value) { "not.an@email" }
109
+
110
+ it "appends an :invalid error" do
111
+ validator.validate_email_format(:username)
112
+ assert_includes(validator.errors[:username], :invalid)
113
+ assert_equal(1, validator.errors[:username].size)
114
+ end
89
115
  end
90
116
  end
91
117
  end
92
118
 
93
119
  describe "#validate_format" do
94
120
  describe "when value does not match the regexp" do
95
- let(:username_value) { "ema8l" }
121
+ describe "when value is not present" do
122
+ let(:username_value) { nil }
96
123
 
97
- it "appends an :invalid error" do
98
- validator.validate_format(:username, /\A[a-z]+\Z/)
99
- assert_includes(validator.errors[:username], :invalid)
100
- assert_equal(1, validator.errors[:username].size)
124
+ it "doesn't append any error" do
125
+ validator.validate_format(:username, /\A[a-z]+\Z/)
126
+
127
+ assert_equal(0, validator.errors[:username].size)
128
+ end
129
+ end
130
+
131
+ describe "when value is present" do
132
+ let(:username_value) { "ema8l" }
133
+
134
+ it "appends an :invalid error" do
135
+ validator.validate_format(:username, /\A[a-z]+\Z/)
136
+ assert_includes(validator.errors[:username], :invalid)
137
+ assert_equal(1, validator.errors[:username].size)
138
+ end
101
139
  end
102
140
  end
103
141
  end
104
142
 
105
143
  describe "#validate_length" do
106
144
  describe "when value size is less than the min" do
107
- let(:username_value) { "ema8l" }
145
+ describe "when value is not present" do
146
+ let(:username_value) { nil }
108
147
 
109
- it "appends a :too_short error" do
110
- validator.validate_length(:username, :min => 8)
111
- assert_includes(validator.errors[:username], :too_short)
112
- assert_equal(1, validator.errors[:username].size)
148
+ it "doesn't append any error" do
149
+ validator.validate_length(:username, :min => 8)
150
+
151
+ assert_equal(0, validator.errors[:username].size)
152
+ end
153
+ end
154
+
155
+ describe "when value is present" do
156
+ let(:username_value) { "ema8l" }
157
+
158
+ it "appends a :too_short error" do
159
+ validator.validate_length(:username, :min => 8)
160
+ assert_includes(validator.errors[:username], :too_short)
161
+ assert_equal(1, validator.errors[:username].size)
162
+ end
113
163
  end
114
164
  end
115
165
 
@@ -126,24 +176,48 @@ describe Organ::Validations do
126
176
 
127
177
  describe "#validate_inclusion" do
128
178
  describe "when is not included in the list" do
129
- let(:username_value) { 1 }
179
+ describe "when value is not present" do
180
+ let(:username_value) { nil }
130
181
 
131
- it "appends a :not_included error" do
132
- validator.validate_inclusion(:username, [2, 3])
133
- assert_includes(validator.errors[:username], :not_included)
134
- assert_equal(1, validator.errors[:username].size)
182
+ it "doesn't append any error" do
183
+ validator.validate_inclusion(:username, [2, 3])
184
+
185
+ assert_equal(0, validator.errors[:username].size)
186
+ end
187
+ end
188
+
189
+ describe "when value is present" do
190
+ let(:username_value) { 1 }
191
+
192
+ it "appends a :not_included error" do
193
+ validator.validate_inclusion(:username, [2, 3])
194
+ assert_includes(validator.errors[:username], :not_included)
195
+ assert_equal(1, validator.errors[:username].size)
196
+ end
135
197
  end
136
198
  end
137
199
  end
138
200
 
139
201
  describe "#validate_range" do
140
202
  describe "when value is less than the min" do
141
- let(:username_value) { 5 }
203
+ describe "when value is not present" do
204
+ let(:username_value) { nil }
142
205
 
143
- it "appends a :less_than error" do
144
- validator.validate_range(:username, :min => 8)
145
- assert_includes(validator.errors[:username], :less_than)
146
- assert_equal(1, validator.errors[:username].size)
206
+ it "doesn't append any error" do
207
+ validator.validate_range(:username, :min => 8)
208
+
209
+ assert_equal(0, validator.errors[:username].size)
210
+ end
211
+ end
212
+
213
+ describe "when value is present" do
214
+ let(:username_value) { 5 }
215
+
216
+ it "appends a :less_than error" do
217
+ validator.validate_range(:username, :min => 8)
218
+ assert_includes(validator.errors[:username], :less_than)
219
+ assert_equal(1, validator.errors[:username].size)
220
+ end
147
221
  end
148
222
  end
149
223
 
@@ -158,4 +232,36 @@ describe Organ::Validations do
158
232
  end
159
233
  end
160
234
 
235
+ describe "#validation_block" do
236
+ describe "when form has no errors" do
237
+ let(:username_value) { "validusername" }
238
+
239
+ it "calls the given block" do
240
+ validator.validate_presence(:username)
241
+
242
+ block_called = 0
243
+
244
+ validator.validation_block do
245
+ block_called += 1
246
+ end
247
+
248
+ assert_equal(1, block_called)
249
+ end
250
+ end
251
+
252
+ describe "when form has errors" do
253
+ it "doesn't call the given block" do
254
+ validator.validate_presence(:username)
255
+
256
+ block_called = 0
257
+
258
+ validator.validation_block do
259
+ block_called += 1
260
+ end
261
+
262
+ assert_equal(0, block_called)
263
+ end
264
+ end
265
+ end
266
+
161
267
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: organ
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastian Borrazas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-02 00:00:00.000000000 Z
11
+ date: 2017-04-13 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A small library for manipulating form-based data with validations and
14
14
  attributes coercion.