value_objects 0.1.0
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 +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +230 -0
- data/lib/value_objects/action_view/cocoon.rb +43 -0
- data/lib/value_objects/action_view.rb +12 -0
- data/lib/value_objects/active_record.rb +56 -0
- data/lib/value_objects/base.rb +70 -0
- data/lib/value_objects/valid_validator.rb +12 -0
- data/lib/value_objects/version.rb +4 -0
- data/lib/value_objects.rb +7 -0
- metadata +137 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fcf100e50deeb0be95ee828543bebc1271b8ccfe
|
4
|
+
data.tar.gz: eb2293813317264b2fcbdfcae89feaa7a8f48298
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 650a0c71dcba21c4ea3774471de37a7b3937319c73d80ae411a396e520dca12bcc2fd7c6570f22791bc6e42add3016f10a3c024b1441195712fc0e5fc4654734
|
7
|
+
data.tar.gz: ed81e88aa8436eb2d76ba35f87346ff55643573cf27726828e3729f1568f388cf072694db9c1267e16caa6055a473cb52d1b3caf7a5cd30e4b058a94e62a01a5
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Matthew Yeow
|
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.md
ADDED
@@ -0,0 +1,230 @@
|
|
1
|
+
# ValueObjects
|
2
|
+
|
3
|
+
Serializable and validatable value objects for ActiveRecord
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'value_objects'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install value_objects
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
### Create the value object class
|
24
|
+
|
25
|
+
The value object class inherits from `ValueObjects::Base`, and attributes are defined with `attr_accessor`:
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
class AddressValue < ValueObjects::Base
|
29
|
+
attr_accessor :street, :postcode, :city
|
30
|
+
end
|
31
|
+
|
32
|
+
address = AddressValue.new(street: '123 Big Street', postcode: '12345', city: 'Metropolis')
|
33
|
+
address.street # => "123 Big Street"
|
34
|
+
address.street = '321 Main St' # => "321 Main St"
|
35
|
+
address.to_hash # => {:street=>"321 Main St", :postcode=>"12345", :city=>"Metropolis"}
|
36
|
+
```
|
37
|
+
|
38
|
+
### Add validations
|
39
|
+
|
40
|
+
Validations can be added using the DSL from `ActiveModel::Validations`:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
class AddressValue < ValueObjects::Base
|
44
|
+
attr_accessor :street, :postcode, :city
|
45
|
+
validates :postcode, presence: true
|
46
|
+
end
|
47
|
+
|
48
|
+
address = AddressValue.new(street: '123 Big Street', city: 'Metropolis')
|
49
|
+
address.valid? # => false
|
50
|
+
address.errors.to_h # => {:postcode=>"can't be blank"}
|
51
|
+
address.postcode = '12345' # => "12345"
|
52
|
+
address.valid? # => true
|
53
|
+
address.errors.to_h # => {}
|
54
|
+
```
|
55
|
+
|
56
|
+
### Serialization with ActiveRecord
|
57
|
+
|
58
|
+
For columns of `json` type, the value object class can be used as the coder for the `serialize` method:
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
class Customer < ActiveRecord::Base
|
62
|
+
serialize :home_address, AddressValue
|
63
|
+
end
|
64
|
+
|
65
|
+
customer = Customer.new
|
66
|
+
customer.home_address = AddressValue.new(street: '123 Big Street', postcode: '12345', city: 'Metropolis')
|
67
|
+
customer.save
|
68
|
+
customer.reload
|
69
|
+
customer.home_address # => #<AddressValue:0x00ba9876543210 @street="123 Big Street", @postcode="12345", @city="Metropolis">
|
70
|
+
```
|
71
|
+
|
72
|
+
For columns of `string` or `text` type, wrap the value object class in a `JsonCoder`:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
class Customer < ActiveRecord::Base
|
76
|
+
serialize :home_address, ValueObjects::ActiveRecord::JsonCoder.new(AddressValue)
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
### Validation with ActiveRecord
|
81
|
+
|
82
|
+
By default, validating the record does not automatically validate the value object.
|
83
|
+
Use the `ValueObjects::ValidValidator` to make this automatic:
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
class Customer < ActiveRecord::Base
|
87
|
+
serialize :home_address, AddressValue
|
88
|
+
validates :home_address, 'value_objects/valid': true
|
89
|
+
validates :home_address, presence: true # other validations are allowed too
|
90
|
+
end
|
91
|
+
|
92
|
+
customer = Customer.new
|
93
|
+
customer.home_address = AddressValue.new(street: '123 Big Street', city: 'Metropolis')
|
94
|
+
customer.valid? # => false
|
95
|
+
customer.errors.to_h # => {:home_address=>"is invalid"}
|
96
|
+
customer.home_address.errors.to_h # => {:postcode=>"can't be blank"}
|
97
|
+
customer = Customer.new
|
98
|
+
customer.valid? # => false
|
99
|
+
customer.errors.to_h # => {:home_address=>"can't be blank"}
|
100
|
+
```
|
101
|
+
|
102
|
+
### With `ValueObjects::ActiveRecord`
|
103
|
+
|
104
|
+
For easy set up of both serialization and validation, `include ValueObjects::ActiveRecord` and invoke `value_object`:
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
class Customer < ActiveRecord::Base
|
108
|
+
include ValueObjects::ActiveRecord
|
109
|
+
value_object :home_address, AddressValue
|
110
|
+
validates :home_address, presence: true
|
111
|
+
end
|
112
|
+
```
|
113
|
+
|
114
|
+
This basically works the same way but also defines the `<attribute>_attributes=` method which can be used to assign the value object using a hash:
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
customer.home_address_attributes = { street: '321 Main St', postcode: '54321', city: 'Micropolis' }
|
118
|
+
customer.home_address # => #<AddressValue:0x00ba9876503210 @street="321 Main St", @postcode="54321", @city="Micropolis">
|
119
|
+
```
|
120
|
+
|
121
|
+
This is functionally similar to what `accepts_nested_attributes_for` does for associations.
|
122
|
+
|
123
|
+
Also, `value_object` will use the `JsonCoder` automatically if it detects that the column type is `string` or `text`.
|
124
|
+
|
125
|
+
Additional options may be passed in to customize validation:
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
class Customer < ActiveRecord::Base
|
129
|
+
include ValueObjects::ActiveRecord
|
130
|
+
value_object :home_address, AddressValue, allow_nil: true
|
131
|
+
end
|
132
|
+
```
|
133
|
+
|
134
|
+
Or, to skip validation entirely:
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
class Customer < ActiveRecord::Base
|
138
|
+
include ValueObjects::ActiveRecord
|
139
|
+
value_object :home_address, AddressValue, no_validation: true
|
140
|
+
end
|
141
|
+
```
|
142
|
+
|
143
|
+
### Value object collections
|
144
|
+
|
145
|
+
Serialization and validation of value object collections are also supported.
|
146
|
+
|
147
|
+
First, create a nested `Collection` class that inherits from `ValueObjects::Base::Collection`:
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
class AddressValue < ValueObjects::Base
|
151
|
+
attr_accessor :street, :postcode, :city
|
152
|
+
validates :postcode, presence: true
|
153
|
+
|
154
|
+
class Collection < Collection
|
155
|
+
end
|
156
|
+
end
|
157
|
+
```
|
158
|
+
|
159
|
+
Then use the nested `Collection` class as the serialization coder:
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
class Customer < ActiveRecord::Base
|
163
|
+
include ValueObjects::ActiveRecord
|
164
|
+
value_object :addresses, AddressValue::Collection
|
165
|
+
validates :addresses, presence: true
|
166
|
+
end
|
167
|
+
|
168
|
+
customer = Customer.new(addresses: [])
|
169
|
+
customer.valid? # => false
|
170
|
+
customer.errors.to_h # => {:addresses=>"can't be blank"}
|
171
|
+
customer.addresses << AddressValue.new(street: '123 Big Street', postcode: '12345', city: 'Metropolis')
|
172
|
+
customer.valid? # => true
|
173
|
+
customer.addresses << AddressValue.new(street: '321 Main St', city: 'Micropolis')
|
174
|
+
customer.valid? # => false
|
175
|
+
customer.errors.to_h # => {:addresses=>"is invalid"}
|
176
|
+
customer.addresses[1].errors.to_h # => {:postcode=>"can't be blank"}
|
177
|
+
```
|
178
|
+
|
179
|
+
The `<attribute>_attributes=` method also functions in much the same way:
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
customer.addresses_attributes = { '0' => { city: 'Micropolis' }, '1' => { city: 'Metropolis' } }
|
183
|
+
customer.addresses # => [#<AddressValue:0x00ba9876543210 @city="Micropolis">, #<AddressValue:0x00ba9876503210 @city="Metropolis">]
|
184
|
+
```
|
185
|
+
|
186
|
+
Except, items with '-1' keys are considered as dummy items and ignored:
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
customer.addresses_attributes = { '0' => { city: 'Micropolis' }, '-1' => { city: 'Metropolis' } }
|
190
|
+
customer.addresses # => [#<AddressValue:0x00ba9876543210 @city="Micropolis">]
|
191
|
+
```
|
192
|
+
|
193
|
+
This is useful when data is submitted via standard HTML forms encoded with the 'application/x-www-form-urlencoded' media type (which cannot represent empty collections). To work around this, a dummy item can be added to the collection with it's key set to '-1' and it will conveniently be ignored when assigned to the value object collection.
|
194
|
+
|
195
|
+
### Integrate with Cocoon
|
196
|
+
|
197
|
+
Put this into a Rails initializer (e.g. `config/initializers/value_objects.rb`):
|
198
|
+
|
199
|
+
```ruby
|
200
|
+
ValueObjects::ActionView.integrate_with :cocoon
|
201
|
+
```
|
202
|
+
|
203
|
+
This will add the `link_to_add_nested_value` & `link_to_remove_nested_value` view helpers.
|
204
|
+
Use them in place of Cocoon's `link_to_add_association` & `link_to_remove_association` when working with nested value objects:
|
205
|
+
|
206
|
+
```ruby
|
207
|
+
# use the attribute name (:addresses) in place of the association name
|
208
|
+
# and supply the value object class as the next argument
|
209
|
+
link_to_add_nested_value 'Add Address', f, :addresses, AddressValue
|
210
|
+
|
211
|
+
# the `f` form builder argument is not needed
|
212
|
+
link_to_remove_nested_value 'Remove Address'
|
213
|
+
```
|
214
|
+
|
215
|
+
## Maintainers
|
216
|
+
|
217
|
+
* Matthew Yeow (https://github.com/tbsmatt), Tinkerbox Studios (https://www.tinkerbox.com.sg/)
|
218
|
+
|
219
|
+
## Contributing
|
220
|
+
|
221
|
+
* Fork the repository.
|
222
|
+
* Make your feature addition or bug fix.
|
223
|
+
* Add tests for it. This is important so we don't break it in a future version unintentionally.
|
224
|
+
* Commit, but do not mess with rakefile or version. (if you want to have your own version, that is fine but bump version in a commit by itself)
|
225
|
+
* Submit a pull request. Bonus points for topic branches.
|
226
|
+
|
227
|
+
## License
|
228
|
+
|
229
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
230
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ValueObjects
|
3
|
+
|
4
|
+
module ActionView
|
5
|
+
|
6
|
+
module Cocoon
|
7
|
+
|
8
|
+
def link_to_add_nested_value(name, f, attribute, value_class, html_options = {}, &block)
|
9
|
+
render_options = html_options.delete(:render_options) || {}
|
10
|
+
partial = html_options.delete(:partial)
|
11
|
+
wrap_object = html_options.delete(:wrap_object)
|
12
|
+
form_name = html_options.delete(:form_name) || 'f'
|
13
|
+
count = html_options.delete(:count).to_i
|
14
|
+
new_object = value_class.new
|
15
|
+
new_object = wrap_object.call(new_object) if wrap_object
|
16
|
+
|
17
|
+
html_options[:class] = [html_options[:class], 'add_fields'].compact.join(' ')
|
18
|
+
html_options[:'data-association'] = attribute
|
19
|
+
html_options[:'data-association-insertion-template'] = CGI.escapeHTML(render_association(attribute, f, new_object, form_name, render_options, partial)).html_safe
|
20
|
+
html_options[:'data-count'] = count if count > 0
|
21
|
+
|
22
|
+
name = capture(&block) if block_given?
|
23
|
+
dummy_input = tag(:input, type: 'hidden', name: "#{f.object_name}[#{attribute}_attributes][-1][_]")
|
24
|
+
content_tag(:a, name, html_options) + dummy_input
|
25
|
+
end
|
26
|
+
|
27
|
+
def link_to_remove_nested_value(name, html_options = {}, &block)
|
28
|
+
wrapper_class = html_options.delete(:wrapper_class)
|
29
|
+
|
30
|
+
html_options[:class] = [html_options[:class], 'remove_fields dynamic'].compact.join(' ')
|
31
|
+
html_options[:'data-wrapper-class'] = wrapper_class if wrapper_class
|
32
|
+
|
33
|
+
name = capture(&block) if block_given?
|
34
|
+
content_tag(:a, name, html_options)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
ActionView::Base.send(:include, ValueObjects::ActionView::Cocoon)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ValueObjects
|
3
|
+
|
4
|
+
module ActiveRecord
|
5
|
+
|
6
|
+
def self.included(base)
|
7
|
+
base.extend self
|
8
|
+
end
|
9
|
+
|
10
|
+
def value_object(attribute, value_class, options = {})
|
11
|
+
type =
|
12
|
+
begin
|
13
|
+
column_for_attribute(attribute)&.type
|
14
|
+
rescue ::ActiveRecord::StatementInvalid
|
15
|
+
# This can happen if `column_for_attribute` is called but the database table does not exist
|
16
|
+
# as will be the case when migrations are run and the model class is loaded by initializers
|
17
|
+
# before the table is created.
|
18
|
+
# This is a workaround to prevent such migrations from failing.
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
coder =
|
22
|
+
case type
|
23
|
+
when :string, :text
|
24
|
+
JsonCoder.new(value_class)
|
25
|
+
else
|
26
|
+
value_class
|
27
|
+
end
|
28
|
+
serialize(attribute, coder)
|
29
|
+
validates_with(::ValueObjects::ValidValidator, options.merge(attributes: [attribute])) unless options[:no_validation]
|
30
|
+
setter = :"#{attribute}="
|
31
|
+
define_method("#{attribute}_attributes=") do |attributes|
|
32
|
+
send(setter, value_class.new(attributes))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class JsonCoder
|
37
|
+
|
38
|
+
EMPTY_ARRAY = [].freeze
|
39
|
+
|
40
|
+
def initialize(value_class)
|
41
|
+
@value_class = value_class
|
42
|
+
end
|
43
|
+
|
44
|
+
def load(value)
|
45
|
+
@value_class.load(JSON.load(value) || EMPTY_ARRAY) if value
|
46
|
+
end
|
47
|
+
|
48
|
+
def dump(value)
|
49
|
+
value.to_json if value
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ValueObjects
|
3
|
+
|
4
|
+
class Base
|
5
|
+
|
6
|
+
include ::ActiveModel::Model
|
7
|
+
|
8
|
+
def ==(other)
|
9
|
+
self.class == other.class && self.class.attrs.all? { |key| public_send(key) == other.public_send(key) }
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_hash
|
13
|
+
self.class.attrs.each_with_object({}) { |key, hash| hash[key] = public_send(key) }
|
14
|
+
end
|
15
|
+
|
16
|
+
class << self
|
17
|
+
|
18
|
+
def load(value)
|
19
|
+
new(value) if value
|
20
|
+
end
|
21
|
+
|
22
|
+
def dump(value)
|
23
|
+
value.to_hash if value
|
24
|
+
end
|
25
|
+
|
26
|
+
def i18n_scope
|
27
|
+
:value_objects
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_reader :attrs
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def attr_accessor(*args)
|
35
|
+
(@attrs ||= []).concat(args)
|
36
|
+
super(*args)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
class Collection
|
42
|
+
|
43
|
+
class << self
|
44
|
+
|
45
|
+
def inherited(subclass)
|
46
|
+
subclass.instance_variable_set(:@value_class, subclass.parent)
|
47
|
+
end
|
48
|
+
|
49
|
+
def new(attributes)
|
50
|
+
# Data encoded with the 'application/x-www-form-urlencoded' media type cannot represent empty collections.
|
51
|
+
# As a workaround, a dummy item can be added to the collection with it's key set to '-1'.
|
52
|
+
# This dummy item will be ignored when initializing the value collection.
|
53
|
+
attributes.map { |k, v| @value_class.new(v) if k != '-1' }.compact
|
54
|
+
end
|
55
|
+
|
56
|
+
def load(values)
|
57
|
+
(values.blank? ? [] : values.map { |value| @value_class.new(value) }) if values
|
58
|
+
end
|
59
|
+
|
60
|
+
def dump(values)
|
61
|
+
values.map(&:to_hash) if values
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ValueObjects
|
3
|
+
|
4
|
+
class ValidValidator < ActiveModel::EachValidator
|
5
|
+
|
6
|
+
def validate_each(record, attribute, value)
|
7
|
+
record.errors.add(attribute, :invalid) unless value && Array(value).count(&:invalid?) == 0
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: value_objects
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matthew Yeow
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-06-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: actionview
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '4.2'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '4.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.11'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.11'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: sqlite3
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.3'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.3'
|
97
|
+
description:
|
98
|
+
email:
|
99
|
+
- matthew.yeow@tinkerbox.com.sg
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- LICENSE.txt
|
105
|
+
- README.md
|
106
|
+
- lib/value_objects.rb
|
107
|
+
- lib/value_objects/action_view.rb
|
108
|
+
- lib/value_objects/action_view/cocoon.rb
|
109
|
+
- lib/value_objects/active_record.rb
|
110
|
+
- lib/value_objects/base.rb
|
111
|
+
- lib/value_objects/valid_validator.rb
|
112
|
+
- lib/value_objects/version.rb
|
113
|
+
homepage: https://github.com/tinkerbox/value_objects
|
114
|
+
licenses:
|
115
|
+
- MIT
|
116
|
+
metadata: {}
|
117
|
+
post_install_message:
|
118
|
+
rdoc_options: []
|
119
|
+
require_paths:
|
120
|
+
- lib
|
121
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '2.2'
|
126
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
requirements: []
|
132
|
+
rubyforge_project:
|
133
|
+
rubygems_version: 2.5.1
|
134
|
+
signing_key:
|
135
|
+
specification_version: 4
|
136
|
+
summary: Serializable and validatable value objects for ActiveRecord
|
137
|
+
test_files: []
|