error_prone 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3c35c189bd7720a73b92c1e9f71286844cc81138
4
+ data.tar.gz: d12ddc14a3dade563cc49f8f3adb6530a22c3d30
5
+ SHA512:
6
+ metadata.gz: e1e02a55550ace75ae30e553ff764c10e2688ce5b0ea90b618c468b1055c955cab532550d0449c4fd17c9ea56bd361478c02cd699b7f10556627b16dad63ec9a
7
+ data.tar.gz: 9726de84a68b951b69ed47cdbf7ce8d37d5685a0548d0bfdca2bbb9b45645935813dbf9f4cec8dfe121fe3573f59bea84710d706b8d0ea41ad61cc16b85dd534
@@ -0,0 +1,2 @@
1
+ ### 0.1.0
2
+ * Created initial feature set.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Zee Spencer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,75 @@
1
+ ErrorProne is a dependency free library that puts control of when, how, and
2
+ where you validate your data in your capable hands.
3
+
4
+ ## Usage
5
+
6
+ ErrorProne has 3 primary modules:
7
+
8
+ * {ErrorProne::Model} - Object to validate
9
+ * {ErrorProne::Rule} - Specific rule to determine a field is valid
10
+ * {ErrorProne::Validator} - Object which collects and applies
11
+ {ErrorProne::Rule Rules} for a {ErrorProne::Model Model}
12
+
13
+ These are mixed in to your objects using the `include` method.
14
+
15
+ ### Example
16
+
17
+ ``` ruby
18
+ class Person < Struct.new(:name, :email)
19
+ include ErrorProne::Model
20
+ end
21
+
22
+ class ValidEmail
23
+ include ErrorProne::Rule
24
+ validates_as :is_email
25
+
26
+ def verify!
27
+ value.include?("@") # WORST. VALIDATION. EVER
28
+ end
29
+
30
+ def message
31
+ :invalid_email
32
+ end
33
+ end
34
+
35
+ include ErrorProne::Validator
36
+ validates :name, :present
37
+ validates :email, :is_email
38
+
39
+ good_person = Person.new("Zee", "zee@example.com")
40
+ validate!(good_person)
41
+ p good_person.errors_for(:name) # []
42
+ p good_person.errors_for(:email) # []
43
+ p good_person.valid? # true
44
+
45
+ bad_person = Person.new(nil, "foo")
46
+ validate!(bad_person)
47
+ p bad_person.valid? # false
48
+ p bad_person.errors_for(:name) # [:missing]
49
+ p bad_person.errors_for(:email) # [:invalid_email]
50
+ ```
51
+
52
+ ## Philosophy
53
+ ### Simple over Easy
54
+ ErrorProne isn't designed to minimize keystrokes. Instead, it exhibits a
55
+ pythonesque preference for expliciteness and minimal dependencies. This results
56
+ in a library that is powerful, portable, and comprehensible. ErrorProne eschews
57
+ metaprogramming in favor of a relatively boring codebase.
58
+
59
+ ### Supportive over Prescriptive
60
+ We rubyists sometimes prefer beauty of DSL regardless of how it prods users
61
+ towards highly coupled objects or locks them into an architecture that is more
62
+ about the library than the problem they're solving. ErrorProne supports your
63
+ design instead of prescribing it.
64
+
65
+ ## Contributing
66
+ OSS is all about the community. Feel free to submit new features, documentation
67
+ chagnes, and requests for help in the following ways:
68
+
69
+ 1. Submit a [pull request](pulls). Explain how your change meets the ErrorProne
70
+ [philosophy](#label-Philosophy). Include reasonable tests and rdoc.
71
+ 2. Open an [issue](issues). Explain how the proposed change meets the ErrorProne
72
+ [philosophy](#label-Philosophy).
73
+ 3. Ask a question on [Stack
74
+ Overflow](http://stackoverflow.com/questions/tagged/error-prone) and tweet
75
+ [@zspencer](http://twitter.com/zspencer) so I can answer it quickly
@@ -0,0 +1,222 @@
1
+ module ErrorProne
2
+
3
+
4
+ # Mixed in to objects you wish to validate.
5
+ #
6
+ # @example
7
+ #
8
+ # class FakeModel < Struct.new(:name)
9
+ # include ErrorProne::Model
10
+ # end
11
+ #
12
+ # model = FakeModel.new
13
+ # model.valid? # true
14
+ # model.add_error(:name, :too_cool)
15
+ # model.valid? # false
16
+ # model.errors_for(:name) # [:too_cool]
17
+
18
+ module Model
19
+
20
+ # @param [Symbol] field The field to find errors for
21
+ # @return [Array] the errors for the given field
22
+ def errors_for(field)
23
+ errors.for(field)
24
+ end
25
+
26
+ # @return [ErrorProne::Errors]
27
+ def errors
28
+ @errors ||= Errors.new
29
+ end
30
+
31
+ # @param [Symbol] field Identifies which field to add an error to
32
+ # @param [Symbol] error Identifies the type of error that occured
33
+ # @return [self] The model itself
34
+ def add_error(field, error)
35
+ errors.add(field, error)
36
+ self
37
+ end
38
+
39
+ # @return [Boolean] false if errors had been added. True if no errors.
40
+ def valid?
41
+ errors.empty?
42
+ end
43
+ end
44
+
45
+ # Mixed in to objects that can verify whether an {ErrorProne::Model} is valid
46
+ # or not.
47
+ #
48
+ # @example
49
+ # class FakeRule
50
+ #
51
+ # include ErrorProne::Rule
52
+ # validates_as :not_nil
53
+ #
54
+ # def verify!
55
+ # !value.nil?
56
+ # end
57
+ #
58
+ # def message
59
+ # :field_nil
60
+ # end
61
+ # end
62
+ #
63
+ module Rule
64
+ module ClassMethods
65
+
66
+ # @param [Symbol] rule_name Name to use when using validates on an {ErrorProne::Validator}
67
+ def validates_as(rule_name)
68
+ RuleSet.available_rules[rule_name] = self
69
+ end
70
+ end
71
+
72
+
73
+ attr_reader :object, :field, :value
74
+ # @param [Object] object Object to verify conforms to a rule
75
+ # @param [Symbol] field Field on the object that must conform to the rule
76
+ # @param [Hash] options often specific to the the Rule
77
+ def initialize(object, field, options = {})
78
+ @object = object
79
+ @field = field
80
+ @options = options
81
+ end
82
+
83
+ # Adds error to the object if verify! fails
84
+ # @return [Boolean]
85
+ def validate!
86
+ @value = object.send(field)
87
+ return true if verify!
88
+ object.add_error(field, message)
89
+ false
90
+ end
91
+
92
+ # Message to add when validate! finds an error. Must override in
93
+ # implementing classes.
94
+ # @return [Symbol]
95
+ def message
96
+ raise "You must set a message for rules to work"
97
+ end
98
+
99
+ # Verifies if the rule is followed. Must override in implementing classes.
100
+ # @return [Boolean]
101
+ def verify!
102
+ raise "You must provide a verify! method for rules to work. verify! should return a boolean"
103
+ end
104
+
105
+ def self.included(klazz)
106
+ klazz.extend(ClassMethods)
107
+ end
108
+ end
109
+
110
+ # Mixed in to objects you wish to use to validate other objects
111
+ #
112
+ # @example
113
+ # class ObjectToValidate < Struct.new(:name)
114
+ # include ErrorProne::Model
115
+ # end
116
+ #
117
+ # class ObjectValidator
118
+ # include ErrorProne::Validator
119
+ # validates :name, :present
120
+ # end
121
+ #
122
+ # object = ObjectToValidate.new(nil)
123
+ # ObjectValidator.new.validate!(object) # false
124
+ # object.valid? # false
125
+ # object.errors_for(:name) # [:missing]
126
+
127
+ module Validator
128
+
129
+ module ClassMethods
130
+ # Contains rules the validator will run when .validate! is called
131
+ #
132
+ # @return (ErrorProne::RuleSet)
133
+ def rules
134
+ @rules ||= RuleSet.new
135
+ end
136
+
137
+
138
+ # Adds a rule the validator runs when .validate! is called.
139
+ #
140
+ # @param (Symbol) field Method to call on the object to validate
141
+ # @param (Symbol) rule Name of rule to apply, defined by {ErrorProne::Rule}.validates_as
142
+ # @param (Hash) options to pass to the {ErrorProne::Rule} when instantiating
143
+ def validates(field, rule, options={})
144
+ rules.add(field, rule, options)
145
+ end
146
+
147
+ # Validates all rules against the given object
148
+ #
149
+ # @param (Object) object Object to validate each rule against
150
+ # @return (Boolean) True if all rules are valid, false otherwise.
151
+ def validate!(object)
152
+ rules.all_valid_for? object
153
+ end
154
+ end
155
+
156
+ # Alias for {ErrorProne::Validator}.validate
157
+ def validate!(object)
158
+ self.class.validate!(object)
159
+ end
160
+
161
+ def self.included(base)
162
+ base.extend(ClassMethods)
163
+ end
164
+
165
+ end
166
+
167
+ class RuleSet < Hash
168
+ def self.available_rules
169
+ @available_rules ||= {}
170
+ end
171
+
172
+ def available_rules
173
+ self.class.available_rules
174
+ end
175
+
176
+ def for(field)
177
+ self[field] ||= []
178
+ end
179
+
180
+ def add(field, rule_name, options = {})
181
+ raise "rule #{rule_name} is not available" unless available_rules.has_key?(rule_name)
182
+ self.for(field).push(rule: available_rules[rule_name], options: options)
183
+ self
184
+ end
185
+
186
+
187
+ def all_valid_for?(object)
188
+ all? do |field, rules|
189
+ rules.all? do |rule_config|
190
+ rule = rule_config[:rule].new(object, field, rule_config[:options])
191
+ rule.validate!
192
+ end
193
+ end
194
+ end
195
+ end
196
+
197
+ class PresenceRule
198
+ include Rule
199
+ validates_as :present
200
+
201
+ def verify!
202
+ [:nil?, :empty?].select { |method| value.respond_to?(method) }.none? { |method|
203
+ value.send(method)
204
+ }
205
+ end
206
+
207
+ def message
208
+ :missing
209
+ end
210
+ end
211
+
212
+ class Errors < Hash
213
+ def add(field, error)
214
+ self.for(field).push(error)
215
+ self
216
+ end
217
+
218
+ def for(field)
219
+ self[field] ||= []
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,3 @@
1
+ module ErrorProne
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: error_prone
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Zee Spencer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-07-21 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: ErrorProne lets you choose where, when, and how to validate data without
14
+ tying you to ORMs or application frameworks.
15
+ email:
16
+ - zee@zeespencer.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - lib/error_prone/version.rb
22
+ - lib/error_prone.rb
23
+ - LICENSE
24
+ - README.markdown
25
+ - CHANGELOG.markdown
26
+ homepage: http://github.com/zspencer/error_prone
27
+ licenses: []
28
+ metadata: {}
29
+ post_install_message:
30
+ rdoc_options: []
31
+ require_paths:
32
+ - lib
33
+ required_ruby_version: !ruby/object:Gem::Requirement
34
+ requirements:
35
+ - - '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ required_rubygems_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ requirements: []
44
+ rubyforge_project:
45
+ rubygems_version: 2.0.3
46
+ signing_key:
47
+ specification_version: 4
48
+ summary: The no-frills, dependency-free data validation library
49
+ test_files: []