hatch 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +8 -8
  2. data/README.md +28 -9
  3. data/hatch.gemspec +1 -1
  4. data/lib/hatch.rb +31 -37
  5. metadata +2 -2
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NWIyNzI5OWMyNjA5ZjQ0ZmE1OWExZDIxYWFhMmYxMWQwMTNjNjM0NQ==
4
+ OTRmYTJkYmNkNDQ1Mzc4YmI0NTI1YTE2MWQ1MGMxNjQ4Y2QyZWY2YQ==
5
5
  data.tar.gz: !binary |-
6
- MzUwYzM2NzI1YmRiNjNhMjYxMjQwYWUyYzZjODNiM2QyMDE4Nzc2Mw==
6
+ MzdhNGMzYzIxMGU5ZWZiMWM5MTkzZDAzYjc2M2U1NmU2MTU1ZmQ5ZQ==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- ZGIxMWE4YTg3OTEzNTllZjA4YjFlNjY1NmU4ZjhiNWQwMmIzN2Q2ODQ1ZDIw
10
- OWZiMDM0MmNjNmRkNTQxZGEzM2QzMDY5YTIxNWExZDFhMjEzYzQzMzg3YWZl
11
- OTBkZDgzYTI4Y2Q1NWJkYmVmMmUxNWNhYjEwOTNkYTNiM2QwZjM=
9
+ NDg3NzVlYTBmM2NlMjA4ZmUxOTFkZDM0ZTM1MDA3ZjM2NjViYzJlMmYzNjA0
10
+ MDM3NTkyYjE4ODFkZjhiMTYwNTA4OTdkZDY1YmU5MTY4OWNhNjViOTAzMGU5
11
+ NDAxMTJlNDNjMzJiMDBlM2ZiZGM4MGYyMTFlZTJkYjkxMmYxMGQ=
12
12
  data.tar.gz: !binary |-
13
- OGU1YmJjYTgzNjY4MGJiMjI4ZDYzOTIxZmVhMmVjMmY0YjcyNTVlNGMyYzJj
14
- M2FjYzYwNzQ0MzMwNDcyNmRjYzdiZWZkNjAzMzZmMTU0ZDEzNjY0ZmIwMGEw
15
- MjY0NTU2M2M4Yjg2Zjc4YTdjZjVmNzZlYWM4ZmRjYmYxNjA5NzU=
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
- To [@pote](https://github.com/pote) for the help, support and company!
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.0'
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 << Validator.validate(attribute,
40
- args[attribute],
41
- validation.error,
42
- &validation.block)
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
- private
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
- def build(validated_attributes)
80
- validation = -> do
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
- if validation.call
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 Validator
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
- errors = new
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
- messages = []
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.0
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-02 00:00:00.000000000 Z
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!