hatch 0.0.6 → 0.0.7
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 +8 -8
- data/README.md +52 -16
- data/hatch.gemspec +1 -1
- data/lib/hatch.rb +30 -7
- data/test/common_validations_test.rb +3 -5
- data/test/errors_test.rb +27 -0
- data/test/validation_test.rb +3 -19
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MzJjNWMxMjRlMzM0OGM0YTk2YWY3MmQ5YjAyZWNiMDZjYjg1YWQ0OA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NzJhNTQyYjJhMTUyOWZmOWE1OTdjMzY2ZDZmMDQ0MmViY2Y5ODEzZA==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MTY4NzUzN2Y3OGYyMWFlYmVmNGVjMTI1NDg5Yjc0Y2JiOGY2YmM4NWQyY2Fm
|
10
|
+
OTFlMTc0Y2Q5ZWE0YmFhODJkNTc4YWY3YjNhMmQ1MDU3ZWQyNzI1ZmIxZmFk
|
11
|
+
ZjA4ZDNlODYwMmY0NTgzMmQyYTY1YTFiMzQwNDc3YzBkMTVlYzY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
M2E5M2QyNzE3YjE1NDRmZWM4MDAzNDg2ZjU1ZmY4YTNhMjRkODcxZjc1Yzg2
|
14
|
+
MmQyMGM4NzY0ZTU1NjIwNGQzNDlkNzc5MmQ4NTFhNjY5MzY3NjhiYmFiMTBk
|
15
|
+
ODQ5M2IwNjI0ZjYzNDdhN2MyMzQ5MWMzODBiNDg1ZWI5M2JjNTU=
|
data/README.md
CHANGED
@@ -1,11 +1,19 @@
|
|
1
1
|
Hatch
|
2
2
|
=====
|
3
3
|
|
4
|
+
Installation
|
5
|
+
------------
|
6
|
+
|
7
|
+
$ gem install hatch
|
8
|
+
|
9
|
+
Usage
|
10
|
+
-----
|
11
|
+
|
4
12
|
An address without a street? A person without a name? Those are not valid objects!
|
5
13
|
Why should you have them hanging around your system?
|
6
14
|
|
7
|
-
Tell
|
8
|
-
the
|
15
|
+
Tell `Hatch` how to certify the attributes of your models, and he will give you
|
16
|
+
the appropriate object.
|
9
17
|
|
10
18
|
If you don't hatch your model with all the correct attributes, it will give you
|
11
19
|
an object representing an invalid instance of it.
|
@@ -29,38 +37,66 @@ end
|
|
29
37
|
address = Address.hatch(street: 'Fake St', number: 1234)
|
30
38
|
address.class
|
31
39
|
# => Address
|
40
|
+
address.valid?
|
41
|
+
# => true
|
32
42
|
|
33
43
|
not_an_address = Address.hatch(street: '', number: 1234)
|
34
44
|
not_an_address.class
|
35
45
|
# => Address::InvalidAddress
|
46
|
+
not_an_address.valid?
|
47
|
+
# => false
|
36
48
|
```
|
37
49
|
|
38
|
-
You declare your attributes to
|
39
|
-
then use
|
50
|
+
You declare your attributes to `Hatch` with the `attributes` message and
|
51
|
+
then use `certify(:attribute, 'error message', &validation)` to verify when an
|
40
52
|
attribute is valid.
|
41
53
|
|
42
|
-
|
43
|
-
|
54
|
+
In case you're wondering, the `Model::InvalidModel` is polymorphic with your
|
55
|
+
`Model` in all the reader methods declared by `attr_reader` or `attr_accessor`
|
56
|
+
|
57
|
+
`Hatch` also supports some common validations we all like to have! You can pass an error
|
58
|
+
of your own or just use the default.
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
class Address
|
62
|
+
include Hatch
|
63
|
+
attributes :street, :number
|
64
|
+
|
65
|
+
certifies(:street, :presence, "This is an error! Where's my street?!")
|
66
|
+
certifies(:number, :positive_number)
|
67
|
+
end
|
68
|
+
```
|
69
|
+
|
70
|
+
Common validations come in the following flavours (along with default errors)
|
71
|
+
|
72
|
+
* `:presence` - `"must be present"`
|
73
|
+
* `:positive_number` - `"must be a positive number"`
|
74
|
+
|
75
|
+
Aaand that's it for the moment. I'll keep on adding more as they come to my mind. If they come
|
76
|
+
to yours first, feel free to add them and PR.
|
77
|
+
|
78
|
+
Errors
|
79
|
+
------
|
80
|
+
|
81
|
+
You'll also get a handy `errors` hash with a couple of super powers.
|
44
82
|
|
45
83
|
```ruby
|
46
84
|
not_an_address = Address.hatch(street: '', number: 1234)
|
47
85
|
not_an_address.class
|
48
86
|
# => Address::InvalidAddress
|
49
87
|
|
50
|
-
not_an_address.errors
|
88
|
+
not_an_address.errors.full_messages
|
51
89
|
# => ['Address must have a street']
|
52
90
|
|
53
|
-
not_an_address.
|
54
|
-
# =>
|
55
|
-
```
|
56
|
-
|
57
|
-
In case you're wondering, the ```Model::InvalidModel``` is polymorphic with your
|
58
|
-
```Model``` in all the reader methods declared by ```attr_reader``` or ```attr_accessor```
|
91
|
+
not_an_address.errors.on(:street)
|
92
|
+
# => 'Address must have a street'
|
59
93
|
|
60
|
-
|
61
|
-
|
94
|
+
not_an_address.errors[:number]
|
95
|
+
# => []
|
62
96
|
|
63
|
-
|
97
|
+
not_an_address.errors.empty?
|
98
|
+
# => false
|
99
|
+
```
|
64
100
|
|
65
101
|
Thanks
|
66
102
|
------
|
data/hatch.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'hatch'
|
3
|
-
s.version = '0.0.
|
3
|
+
s.version = '0.0.7'
|
4
4
|
s.date = Time.now.strftime('%Y-%m-%d')
|
5
5
|
s.summary = 'Keep valid objects only'
|
6
6
|
s.description = "An address without a street? A person without a name? You don't need no invalid objects!"
|
data/lib/hatch.rb
CHANGED
@@ -58,7 +58,7 @@ module Hatch
|
|
58
58
|
|
59
59
|
def initialize(*validated_attributes)
|
60
60
|
@validated_attributes = validated_attributes
|
61
|
-
|
61
|
+
@errors = Errors.build(@validated_attributes)
|
62
62
|
respond_to_instance_methods
|
63
63
|
end
|
64
64
|
|
@@ -80,12 +80,6 @@ module Hatch
|
|
80
80
|
self.class.send :define_method, attribute.attr, -> {attribute.value}
|
81
81
|
end
|
82
82
|
end
|
83
|
-
|
84
|
-
def select_errors
|
85
|
-
@errors = @validated_attributes.select do |validated_attribute|
|
86
|
-
validated_attribute.invalid?
|
87
|
-
end.map(&:error)
|
88
|
-
end
|
89
83
|
end
|
90
84
|
|
91
85
|
private
|
@@ -151,5 +145,34 @@ module Hatch
|
|
151
145
|
new(error || "must be a positive number") {|value| !value.nil? && value > 0}
|
152
146
|
end
|
153
147
|
end
|
148
|
+
|
149
|
+
class Errors < Hash
|
150
|
+
def self.build(validated_attributes)
|
151
|
+
errors = new
|
152
|
+
validated_attributes.each do |validated_attribute|
|
153
|
+
if validated_attribute.invalid?
|
154
|
+
errors[validated_attribute.attr] = validated_attribute.error
|
155
|
+
else
|
156
|
+
errors[validated_attribute.attr] = []
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
errors
|
161
|
+
end
|
162
|
+
|
163
|
+
def on(attr)
|
164
|
+
self[attr]
|
165
|
+
end
|
166
|
+
|
167
|
+
def full_messages
|
168
|
+
messages = []
|
169
|
+
values.each {|value| messages << value unless value.empty?}
|
170
|
+
messages
|
171
|
+
end
|
172
|
+
|
173
|
+
def empty?
|
174
|
+
full_messages.empty?
|
175
|
+
end
|
176
|
+
end
|
154
177
|
end
|
155
178
|
|
@@ -13,13 +13,11 @@ end
|
|
13
13
|
class CommonValidationsTest < Test::Unit::TestCase
|
14
14
|
def test_presence
|
15
15
|
common_stuff = CommonStuff.hatch(present: nil, positive: 1)
|
16
|
-
|
17
|
-
assert common_stuff.errors.include?("must be present")
|
16
|
+
assert_equal 'must be present', common_stuff.errors.on(:present)
|
18
17
|
end
|
19
18
|
|
20
19
|
def test_positive_number
|
21
|
-
common_stuff = CommonStuff.hatch(present:
|
22
|
-
|
23
|
-
assert common_stuff.errors.include?("must be a positive number")
|
20
|
+
common_stuff = CommonStuff.hatch(present: 'here', positive: -1)
|
21
|
+
assert_equal 'must be a positive number', common_stuff.errors.on(:positive)
|
24
22
|
end
|
25
23
|
end
|
data/test/errors_test.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative 'support/helper'
|
2
|
+
require_relative 'support/address'
|
3
|
+
|
4
|
+
class ErrorsTest < Test::Unit::TestCase
|
5
|
+
def initialize(*args)
|
6
|
+
@address = Address.hatch(city: 'Buenos Aires', street: '', number: -1)
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_errors_on
|
11
|
+
assert @address.errors.on(:city).empty?
|
12
|
+
assert_equal 'Address must have a street', @address.errors.on(:street)
|
13
|
+
assert_equal 'Address must have a positive number', @address.errors.on(:number)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_hash_accessor
|
17
|
+
assert @address.errors[:city].empty?
|
18
|
+
assert_equal 'Address must have a street', @address.errors[:street]
|
19
|
+
assert_equal 'Address must have a positive number', @address.errors[:number]
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_errors_full_messages
|
23
|
+
assert @address.errors.full_messages.include?('Address must have a street')
|
24
|
+
assert @address.errors.full_messages.include?('Address must have a positive number')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
data/test/validation_test.rb
CHANGED
@@ -1,33 +1,17 @@
|
|
1
1
|
require_relative 'support/helper'
|
2
2
|
require_relative 'support/address'
|
3
3
|
|
4
|
-
class
|
4
|
+
class ValidationTest < Test::Unit::TestCase
|
5
5
|
def test_valid
|
6
|
-
address = Address.hatch(street:
|
6
|
+
address = Address.hatch(street: 'Fake St', city: 'Buenos Aires', number: 1234)
|
7
7
|
assert address.is_a?(Address)
|
8
|
-
assert_equal address.instance_variable_get("@street"), "Fake St"
|
9
|
-
assert_equal address.instance_variable_get("@number"), 1234
|
10
|
-
assert_equal address.instance_variable_get("@city"), "Buenos Aires"
|
11
|
-
|
12
|
-
assert address.respond_to?(:errors)
|
13
|
-
assert address.errors.empty?
|
14
8
|
assert address.respond_to?(:valid?)
|
15
9
|
assert address.valid?
|
16
10
|
end
|
17
11
|
|
18
12
|
def test_invalid
|
19
|
-
address = Address.hatch(city:
|
20
|
-
assert address.is_a?(Address::InvalidAddress)
|
21
|
-
assert address.errors.include?("Address must have a street")
|
22
|
-
assert !address.errors.include?("Address must have a positive number")
|
23
|
-
assert !address.errors.include?("Address must have a city")
|
24
|
-
|
25
|
-
address = Address.hatch(street: "", number: -4)
|
13
|
+
address = Address.hatch(city: 'Buenos Aires', street: '', number: 1234)
|
26
14
|
assert address.is_a?(Address::InvalidAddress)
|
27
|
-
assert address.errors.include?("Address must have a street")
|
28
|
-
assert address.errors.include?("Address must have a positive number")
|
29
|
-
assert address.errors.include?("Address must have a city")
|
30
|
-
|
31
15
|
assert address.respond_to?(:valid?)
|
32
16
|
assert !address.valid?
|
33
17
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hatch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lucas Tolchinsky
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-05-
|
11
|
+
date: 2013-05-31 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: An address without a street? A person without a name? You don't need
|
14
14
|
no invalid objects!
|
@@ -22,6 +22,7 @@ files:
|
|
22
22
|
- hatch.gemspec
|
23
23
|
- Rakefile
|
24
24
|
- test/common_validations_test.rb
|
25
|
+
- test/errors_test.rb
|
25
26
|
- test/polymorphism_test.rb
|
26
27
|
- test/validation_test.rb
|
27
28
|
- lib/hatch.rb
|