validated_object 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 97d91eb8801c44a0daecab2f6bf5e66c1dc34908
4
- data.tar.gz: b53ae1848ed9176217969907ff95d4ceb6f0d06b
2
+ SHA256:
3
+ metadata.gz: ba509cb442a5ef4c67d7186bd58b329551c00e137ec2c2b1cd7c4e268b92344a
4
+ data.tar.gz: 79a4f93be0f9919bf189f01258ed0379382df90aa01bc69a5ae883d924d53527
5
5
  SHA512:
6
- metadata.gz: 7df6a6cacb4a691183fe606828b572a74e08b139d136e8e6826e5fd2ff3f441443b2f4ef451da96a65040075a46ecfee7e123da9f1ed911308c26b586e0482fe
7
- data.tar.gz: 86ff719a5c3f23f76f843c049a1071b5ff79e6b20953ca482a3cedf33904adde167553d6efce284e067a0f69bb3841534f1bceb2d29a6bd01ed1dacd77bd8931
6
+ metadata.gz: d626a9f7e53258a92e5a0fa3a8cfabf4c7ba38e2c960466e29aaf98dacb7e433c02e3facaca3d2c96a3bd769077a3c3d6e1378b9631a48b6e307db88c8b91f98
7
+ data.tar.gz: 73771320ac4176387bbe336057c2459b5772898a68b380518e149f93af8a29243312462adda6f498a15fb777cb8e803e0db684bc41c130fc316135b63dcc9dac
data/.travis.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.1
4
3
  - 2.2.2
4
+ - 2.3.1
5
5
  before_install: gem install bundler -v 1.10.6
data/README.md CHANGED
@@ -2,78 +2,133 @@
2
2
 
3
3
  # ValidatedObject
4
4
 
5
- Uses
6
- [ActiveModel::Validations](http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates)
7
- to create self-validating Plain Old Ruby objects. I wrote it for helping with CSV data imports into my Rails apps.
8
- Very readable error messages are also important in that context, to track down parsing errors. This gem provides those too.
5
+ Plain Old Ruby Objects + Rails Validations = self-checking Ruby objects.
9
6
 
10
7
 
11
- ## Installation
8
+ ## Goals
12
9
 
13
- Add this line to your application's Gemfile:
10
+ * Very readable error messages
11
+ * Clean, minimal syntax
14
12
 
15
- ```ruby
16
- gem 'validated_object'
17
- ```
13
+ This is a small layer around
14
+ [ActiveModel::Validations](http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates). (About 18 lines of code.) So if you know how to use Rails Validations, you're good to go. I wrote this to help with CSV data imports and [website microdata generation](https://github.com/dogweather/schema-dot-org).
18
15
 
19
- And then execute:
20
-
21
- $ bundle
22
-
23
- Or install it yourself as:
24
-
25
- $ gem install validated_object
26
16
 
27
17
  ## Usage
28
18
 
29
19
 
30
20
  ### Writing a self-validating object
31
21
 
32
- All of the [ActiveModel::Validations](http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates) are available, plus a new one, `TypeValidator`.
22
+ All of the [ActiveModel::Validations](http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates) are available, plus a new one, `TypeValidator`.
33
23
 
34
24
  ```ruby
35
25
  class Dog < ValidatedObject::Base
36
- attr_accessor :name, :birthday
26
+ attr_accessor :name, :birthday # attr_reader is supported as well for read-only attributes
37
27
 
38
28
  validates :name, presence: true
39
- validates :birthday, type: Date, allow_nil: true
29
+ validates :birthday, type: Date, allow_nil: true # Strongly typed but optional
40
30
  end
41
31
  ```
42
32
 
33
+ The `TypeValidator` is what enables `type: Date`, above. All classes can be checked, as well as a pseudo-class `Boolean`. E.g.:
34
+
35
+ ```ruby
36
+ #...
37
+ validates :premium_membership, type: Boolean
38
+ #...
39
+ ```
40
+
43
41
  ### Instantiating and automatically validating
44
42
 
45
43
  ```ruby
46
- # The dog1 instance validates itself at the end of instantiation.
47
- # Here, it succeeds and so doesn't raise an exception.
48
- dog1 = Dog.new do |d|
49
- d.name = 'Spot'
50
- end
44
+ # This Dog instance validates itself at the end of instantiation.
45
+ spot = Dog.new(name: 'Spot')
46
+ ```
47
+
48
+ ```ruby
49
+ # We can also explicitly test for validity because all of
50
+ # ActiveModel::Validations is available.
51
+ spot.valid? # => true
52
+
53
+ spot.birthday = Date.new(2015, 1, 23)
54
+ spot.valid? # => true
55
+ ```
51
56
 
52
- # We can also explicitly test for validity
53
- dog1.valid? # => true
57
+ ### Good error messages
54
58
 
55
- dog1.birthday = Date.new(2015, 1, 23)
56
- dog1.valid? # => true
59
+ Any of the standard Validations methods can be
60
+ used to test an instance, plus the custom `check_validations!` convenience method:
61
+
62
+ ```ruby
63
+ spot.birthday = '2015-01-23'
64
+ spot.valid? # => false
65
+ spot.check_validations! # => ArgumentError: Birthday is class String, not Date
57
66
  ```
58
67
 
59
- ### Making an instance _invalid_
68
+ Note the clear, explicit error message. These are great when reading a log
69
+ file following a data import. It describes all the invalid conditions. Let's
70
+ test it by making another attribute invalid:
60
71
 
61
72
  ```ruby
62
- dog1.birthday = '2015-01-23'
63
- dog1.valid? # => false
64
- dog1.check_validations! # => ArgumentError: Birthday is class String, not Date
73
+ spot.name = nil
74
+ spot.check_validations! # => ArgumentError: Name can't be blank; Birthday is class String, not Date
65
75
  ```
66
76
 
67
77
 
78
+ ### Use in parsing data
79
+
80
+ I often use a validated object in a loop to import data, e.g.:
81
+
82
+ ```ruby
83
+ # Import a CSV file of dogs
84
+ dogs = []
85
+ csv.next_row do |row|
86
+ begin
87
+ dogs << Dog.new(name: row.name)
88
+ rescue ArgumentError => e
89
+ logger.warn(e)
90
+ end
91
+ end
92
+ ```
93
+
94
+ The result is that `dogs` is an array of guaranteed valid Dog objects. And the
95
+ error log lists unparseable rows with good info for tracking down problems in
96
+ the data.
97
+
98
+ ## Installation
99
+
100
+ Add this line to your application's Gemfile:
101
+
102
+ ```ruby
103
+ gem 'validated_object'
104
+ ```
105
+
106
+ And then execute:
107
+
108
+ $ bundle
109
+
110
+ Or install it yourself as:
111
+
112
+ $ gem install validated_object
113
+
114
+
115
+
68
116
  ## Development
69
117
 
70
- (TODO: Verify these instructions.) After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
118
+ (TODO: Verify these instructions.) After checking out the repo, run `bin/setup`
119
+ to install dependencies. Then, run `rake spec` to run the tests. You can also
120
+ run `bin/console` for an interactive prompt that will allow you to experiment.
71
121
 
72
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
122
+ To install this gem onto your local machine, run `bundle exec rake install`. To
123
+ release a new version, update the version number in `version.rb`, and then run
124
+ `bundle exec rake release`, which will create a git tag for the version, push
125
+ git commits and tags, and push the `.gem` file to
126
+ [rubygems.org](https://rubygems.org).
73
127
 
74
128
  ## Contributing
75
129
 
76
- Bug reports and pull requests are welcome on GitHub at https://github.com/dogweather/validated_object.
130
+ Bug reports and pull requests are welcome on GitHub at
131
+ https://github.com/dogweather/validated_object.
77
132
 
78
133
 
79
134
  ## License
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module ValidatedObject
2
- VERSION = '1.1.0'.freeze
3
+ VERSION = '2.0.0'.freeze
3
4
  end
@@ -21,9 +21,7 @@ module ValidatedObject
21
21
  # @example Instantiating and automatically validating
22
22
  # # The dog1 instance validates itself at the end of instantiation.
23
23
  # # Here, it succeeds and so doesn't raise an exception.
24
- # dog1 = Dog.new do |d|
25
- # d.name = 'Spot'
26
- # end
24
+ # dog1 = Dog.new name: 'Spot'
27
25
  #
28
26
  # # We can also explicitly test for validity
29
27
  # dog1.valid? # => true
@@ -42,19 +40,24 @@ module ValidatedObject
42
40
  class Base
43
41
  include ActiveModel::Validations
44
42
 
43
+ EMPTY_HASH = {}.freeze
44
+
45
45
  # Implements a pseudo-boolean class.
46
46
  class Boolean
47
47
  end
48
48
 
49
49
  # Instantiate and validate a new object.
50
- #
51
- # @yieldparam [ValidatedObject] new_object the yielded new object
52
- # for configuration.
50
+ # @example
51
+ # maru = Dog.new(birthday: Date.today, name: 'Maru')
53
52
  #
54
53
  # @raise [ArgumentError] if the object is not valid at the
55
- # end of initialization.
56
- def initialize
57
- yield(self)
54
+ # end of initialization or `attributes` is not a Hash.
55
+ def initialize(attributes=EMPTY_HASH)
56
+ raise ArgumentError, "#{attributes} is not a Hash" unless attributes.is_a?(Hash)
57
+
58
+ attributes.keys.each do |key|
59
+ self.instance_variable_set "@#{key}".to_sym, attributes.fetch(key)
60
+ end
58
61
  check_validations!
59
62
  self
60
63
  end
@@ -73,8 +76,8 @@ module ValidatedObject
73
76
  # @example Ensure that weight is a number
74
77
  # class Dog < ValidatedObject::Base
75
78
  # attr_accessor :weight, :neutered
76
- # validates :weight, type: Numeric
77
- # validates :neutered, type: Boolean
79
+ # validates :weight, type: Numeric # Typed and required
80
+ # validates :neutered, type: Boolean, allow_nil: true # Typed but optional
78
81
  # end
79
82
  class TypeValidator < ActiveModel::EachValidator
80
83
  # @return [nil]
@@ -87,7 +90,7 @@ module ValidatedObject
87
90
  return if value.is_a?(expected_class)
88
91
  end
89
92
 
90
- msg = options[:message] || "is class #{value.class}, not #{expected_class}"
93
+ msg = options[:message] || "is a #{value.class}, not a #{expected_class}"
91
94
  record.errors.add attribute, msg
92
95
  end
93
96
  end
data/script/demo.rb ADDED
@@ -0,0 +1,17 @@
1
+ require 'date'
2
+ require 'validated_object'
3
+
4
+ class Dog < ValidatedObject::Base
5
+ attr_reader :name, :birthday
6
+ validates :name, presence: true
7
+ validates :birthday, type: Date, allow_nil: true
8
+ end
9
+
10
+ phoebe = Dog.new(name: 'Phoebe')
11
+ puts phoebe.inspect
12
+
13
+ maru = Dog.new(birthday: Date.today, name: 'Maru')
14
+ puts maru.inspect
15
+
16
+ paris = Dog.new
17
+ puts paris.inspect
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: validated_object
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robb Shecter
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-04-13 00:00:00.000000000 Z
11
+ date: 2018-02-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -85,6 +85,7 @@ files:
85
85
  - bin/setup
86
86
  - lib/validated_object.rb
87
87
  - lib/validated_object/version.rb
88
+ - script/demo.rb
88
89
  - validated_object.gemspec
89
90
  homepage: https://github.com/dogweather/validated_object
90
91
  licenses:
@@ -107,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
107
108
  version: '0'
108
109
  requirements: []
109
110
  rubyforge_project:
110
- rubygems_version: 2.5.0
111
+ rubygems_version: 2.7.6
111
112
  signing_key:
112
113
  specification_version: 4
113
114
  summary: Self-validating plain Ruby objects.