hatch 0.1.0 → 0.1.1
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 +28 -9
- data/hatch.gemspec +1 -1
- data/lib/hatch.rb +31 -37
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
OTRmYTJkYmNkNDQ1Mzc4YmI0NTI1YTE2MWQ1MGMxNjQ4Y2QyZWY2YQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MzdhNGMzYzIxMGU5ZWZiMWM5MTkzZDAzYjc2M2U1NmU2MTU1ZmQ5ZQ==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NDg3NzVlYTBmM2NlMjA4ZmUxOTFkZDM0ZTM1MDA3ZjM2NjViYzJlMmYzNjA0
|
10
|
+
MDM3NTkyYjE4ODFkZjhiMTYwNTA4OTdkZDY1YmU5MTY4OWNhNjViOTAzMGU5
|
11
|
+
NDAxMTJlNDNjMzJiMDBlM2ZiZGM4MGYyMTFlZTJkYjkxMmYxMGQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MDRjMGNkMmI0ZDExMDBjY2Q0NWI0YzdjYmE5NGE1MDU5YjJlMTc1NjkxZGM5
|
14
|
+
MjM5OGQ1ZjU5ODk0ZmZlODY5NmU2OTA1NzdlYzZkNDUwYzA2YzBlM2FjZmFj
|
15
|
+
YmE4MDIyMTc1MmY2NWYxMzNhODc2OWFkZDRjMjA3Mjc5MDA3M2U=
|
data/README.md
CHANGED
@@ -12,8 +12,7 @@ Usage
|
|
12
12
|
An address without a street? A person without a name? Those are not valid objects!
|
13
13
|
Why should you have them hanging around your system?
|
14
14
|
|
15
|
-
Tell `Hatch` how to certify the attributes of your models, and it will give you
|
16
|
-
the appropriate object.
|
15
|
+
Tell `Hatch` how to certify the attributes of your models, and it will give you the appropriate object.
|
17
16
|
|
18
17
|
If you don't hatch your model with all the correct attributes, you'll get an object representing an invalid instance of it.
|
19
18
|
|
@@ -45,11 +44,9 @@ not_an_address.valid?
|
|
45
44
|
# => false
|
46
45
|
```
|
47
46
|
|
48
|
-
Use `certify(:attribute, 'error message', &validation)` to verify when an
|
49
|
-
attribute is valid.
|
47
|
+
Use `certify(:attribute, 'error message', &validation)` to verify when an attribute is valid.
|
50
48
|
|
51
|
-
In case you're wondering, the `Model::InvalidModel` is polymorphic with your
|
52
|
-
`Model` in all the reader methods declared by `attr_reader` or `attr_accessor`
|
49
|
+
In case you're wondering, the `Model::InvalidModel` is polymorphic with your `Model` in all the reader methods declared by `attr_reader` or `attr_accessor`
|
53
50
|
|
54
51
|
`Hatch` also supports some common validations we all like to have!
|
55
52
|
`certifies(:attribute, :validation, 'error message')` will do the trick.
|
@@ -68,8 +65,7 @@ Common validations come in the following flavours (along with default error mess
|
|
68
65
|
* `:presence` - `"must be present"`
|
69
66
|
* `:positive_number` - `"must be a positive number"`
|
70
67
|
|
71
|
-
Aaand that's it for the moment. I'll keep on adding more as they come to my mind. If they come
|
72
|
-
to yours first, feel free to add them and PR.
|
68
|
+
Aaand that's it for the moment. I'll keep on adding more as they come to my mind. If they come to yours first, feel free to add them and PR.
|
73
69
|
|
74
70
|
Errors
|
75
71
|
------
|
@@ -94,10 +90,33 @@ not_an_address.errors.empty?
|
|
94
90
|
# => false
|
95
91
|
```
|
96
92
|
|
93
|
+
One of the nicest things about `Hatch` is that errors can be any object of your desire! Power to thy user.
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
class LowAwesomenessError
|
97
|
+
attr_accessor :code, :message
|
98
|
+
end
|
99
|
+
|
100
|
+
class Address
|
101
|
+
include Hatch
|
102
|
+
|
103
|
+
error = LowAwesomenessError.new
|
104
|
+
# => #<LowAwesomenessError:0x007fdb3458eeb0>
|
105
|
+
error.code, error.message = :moar_awesome_plz, 'this is not awesome enough'
|
106
|
+
|
107
|
+
certifies(:street, :presence, error)
|
108
|
+
end
|
109
|
+
|
110
|
+
not_an_address = Address.hatch(street: '')
|
111
|
+
not_an_address.errors.on(:street)
|
112
|
+
# => #<LowAwesomenessError:0x007fdb3458eeb0 @code=:moar_awesome_plz, @message="this is not awesome enough">
|
113
|
+
```
|
114
|
+
|
97
115
|
Thanks
|
98
116
|
------
|
99
117
|
|
100
|
-
|
118
|
+
* [@pote](https://github.com/pote) for the help, support and company!
|
119
|
+
* [@munshkr](https://github.com/munshkr) for testing and playing around with it.
|
101
120
|
|
102
121
|
License
|
103
122
|
-------
|
data/hatch.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'hatch'
|
3
|
-
s.version = '0.1.
|
3
|
+
s.version = '0.1.1'
|
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
@@ -36,10 +36,10 @@ module Hatch
|
|
36
36
|
def hatch(args = {})
|
37
37
|
validated_attributes = []
|
38
38
|
@@validations[self.to_s.to_sym].each_pair do |attribute, validation|
|
39
|
-
validated_attributes <<
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
validated_attributes << ValidatedAttribute.validate(attribute,
|
40
|
+
args[attribute],
|
41
|
+
validation.error,
|
42
|
+
&validation.block)
|
43
43
|
end
|
44
44
|
|
45
45
|
build(validated_attributes)
|
@@ -61,32 +61,25 @@ module Hatch
|
|
61
61
|
private
|
62
62
|
|
63
63
|
def respond_to_instance_methods
|
64
|
-
extended_klass = Kernel.const_get(self.class.to_s.split("Invalid").last)
|
65
|
-
address_instance_methods = extended_klass.instance_methods(false)
|
66
|
-
|
67
|
-
attributes_with_reader = @validated_attributes.select do |validated_attribute|
|
68
|
-
address_instance_methods.include?(validated_attribute.attr)
|
69
|
-
end
|
70
|
-
|
71
64
|
attributes_with_reader.each do |attribute|
|
72
65
|
self.class.send :define_method, attribute.attr, -> {attribute.value}
|
73
66
|
end
|
74
67
|
end
|
75
|
-
end
|
76
68
|
|
77
|
-
|
69
|
+
def attributes_with_reader
|
70
|
+
extended_klass = Kernel.const_get(self.class.to_s.split("Invalid").last)
|
71
|
+
instance_methods = extended_klass.instance_methods(false)
|
78
72
|
|
79
|
-
|
80
|
-
|
81
|
-
valid = true
|
82
|
-
validated_attributes.each do |validated_attribute|
|
83
|
-
valid = valid && validated_attribute.valid?
|
73
|
+
@validated_attributes.select do |validated_attribute|
|
74
|
+
instance_methods.include?(validated_attribute.attr)
|
84
75
|
end
|
85
|
-
|
86
|
-
valid
|
87
76
|
end
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
88
80
|
|
89
|
-
|
81
|
+
def build(validated_attributes)
|
82
|
+
if all_attributes_valid?(validated_attributes)
|
90
83
|
set_instance_variables(new, *validated_attributes)
|
91
84
|
else
|
92
85
|
const_get("Invalid#{self}").new(*validated_attributes)
|
@@ -99,9 +92,13 @@ module Hatch
|
|
99
92
|
end
|
100
93
|
instance
|
101
94
|
end
|
95
|
+
|
96
|
+
def all_attributes_valid?(validated_attributes)
|
97
|
+
validated_attributes.map(&:valid?).reduce(true, :&)
|
98
|
+
end
|
102
99
|
end
|
103
100
|
|
104
|
-
class
|
101
|
+
class ValidatedAttribute
|
105
102
|
attr_reader :attr, :value, :error
|
106
103
|
|
107
104
|
def self.validate(attr, value, error, &block)
|
@@ -125,8 +122,7 @@ module Hatch
|
|
125
122
|
attr_reader :error, :block
|
126
123
|
|
127
124
|
def initialize(error, &block)
|
128
|
-
@error = error
|
129
|
-
@block = block
|
125
|
+
@error, @block = error, block
|
130
126
|
end
|
131
127
|
|
132
128
|
def self.presence(error)
|
@@ -140,16 +136,7 @@ module Hatch
|
|
140
136
|
|
141
137
|
class Errors < Hash
|
142
138
|
def self.build(validated_attributes)
|
143
|
-
|
144
|
-
validated_attributes.each do |validated_attribute|
|
145
|
-
if validated_attribute.invalid?
|
146
|
-
errors[validated_attribute.attr] = validated_attribute.error
|
147
|
-
else
|
148
|
-
errors[validated_attribute.attr] = []
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
errors
|
139
|
+
self[attributes_and_errors(validated_attributes)]
|
153
140
|
end
|
154
141
|
|
155
142
|
def on(attr)
|
@@ -157,14 +144,21 @@ module Hatch
|
|
157
144
|
end
|
158
145
|
|
159
146
|
def full_messages
|
160
|
-
|
161
|
-
values.each {|value| messages << value unless value.empty?}
|
162
|
-
messages
|
147
|
+
values.reject {|value| value.empty?}
|
163
148
|
end
|
164
149
|
|
165
150
|
def empty?
|
166
151
|
full_messages.empty?
|
167
152
|
end
|
153
|
+
|
154
|
+
private
|
155
|
+
|
156
|
+
def self.attributes_and_errors(validated_attributes)
|
157
|
+
validated_attributes.map do |validated_attribute|
|
158
|
+
[validated_attribute.attr,
|
159
|
+
validated_attribute.invalid? ? validated_attribute.error : [] ]
|
160
|
+
end
|
161
|
+
end
|
168
162
|
end
|
169
163
|
end
|
170
164
|
|
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.1.
|
4
|
+
version: 0.1.1
|
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-06-
|
11
|
+
date: 2013-06-18 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!
|