shallow_attributes 0.9.2 → 0.9.3
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 +4 -4
- data/.travis.yml +0 -2
- data/Gemfile +1 -0
- data/README.md +121 -7
- data/bench/allocation.rb +56 -0
- data/lib/shallow_attributes/class_methods.rb +55 -3
- data/lib/shallow_attributes/instance_methods.rb +56 -25
- data/lib/shallow_attributes/type/array.rb +10 -2
- data/lib/shallow_attributes/type/boolean.rb +2 -2
- data/lib/shallow_attributes/type/date_time.rb +4 -2
- data/lib/shallow_attributes/type/float.rb +3 -3
- data/lib/shallow_attributes/type/integer.rb +3 -3
- data/lib/shallow_attributes/type/string.rb +2 -2
- data/lib/shallow_attributes/type/time.rb +2 -2
- data/lib/shallow_attributes/type.rb +4 -4
- data/lib/shallow_attributes/version.rb +1 -1
- data/lib/shallow_attributes.rb +6 -1
- data/shallow_attributes.gemspec +1 -0
- metadata +18 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 266928421c7c866fce01375d6046ed426d55a26b
|
4
|
+
data.tar.gz: 6bb003cb52f7617a42b2ba881f01dab7f9feca41
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6bc35f1b034ed265bc43a7d6579a562966ed55a9533ae56fe02ce9a9253b902a8f4a145893265974ad341e4db01e7e83e18fb414c27cc8b52713a0c8cbe2d762
|
7
|
+
data.tar.gz: ef3fcde22033a7aedacc715473444c3bde6b0938f26446ddeb8f592cbb42fe773122c1bb70916d8f576b6e18e7bb4194620dda3bdb5bbfa9b46f9b77267611ff
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# ShallowAttributes
|
2
|
+
|
2
3
|
[](https://travis-ci.org/davydovanton/shallow_attributes)
|
3
4
|
[](https://codeclimate.com/github/davydovanton/shallow_attributes)
|
4
5
|
[](https://coveralls.io/github/davydovanton/shallow_attributes?branch=master)
|
@@ -14,13 +15,13 @@ or [attrio][attrio-link]. However, the disadvantage of these gems is performance
|
|
14
15
|
of `ShallowAttributes` is to provide a simple solution which is similar to the `Virtus` API, simple, fast,
|
15
16
|
understandable and extendable.
|
16
17
|
|
17
|
-
This is [the performance benchmark][performance-benchmark] of ShallowAttributes compared to
|
18
|
+
This is [the performance benchmark][performance-benchmark] of ShallowAttributes compared to Virtus gems.
|
18
19
|
|
19
20
|
## Installation
|
20
21
|
|
21
22
|
Add this line to your application's Gemfile:
|
22
23
|
|
23
|
-
```ruby
|
24
|
+
``` ruby
|
24
25
|
gem 'shallow_attributes'
|
25
26
|
```
|
26
27
|
|
@@ -33,20 +34,25 @@ Or install it yourself as:
|
|
33
34
|
$ gem install shallow_attributes
|
34
35
|
|
35
36
|
## Examples
|
37
|
+
|
36
38
|
### Table of contents
|
39
|
+
|
37
40
|
* [Using ShallowAttributes with Classes](#using-shallowattributes-with-classes)
|
38
41
|
* [Default Values](#default-values)
|
42
|
+
* [Mandatory Attributes](#mandatory-attributes)
|
39
43
|
* [Embedded Value](#embedded-value)
|
40
44
|
* [Custom Coercions](#custom-coercions)
|
41
45
|
* [Collection Member Coercions](#collection-member-coercions)
|
42
46
|
* [Note about Member Coercions](#important-note-about-member-coercions)
|
43
47
|
* [Overriding setters](#overriding-setters)
|
44
|
-
* [ActiveModel
|
48
|
+
* [ActiveModel compatibility](#activemodel-compatibility)
|
49
|
+
* [Dry-types](#dry-types)
|
45
50
|
|
46
51
|
### Using ShallowAttributes with Classes
|
52
|
+
|
47
53
|
You can create classes extended with Virtus and define attributes:
|
48
54
|
|
49
|
-
```ruby
|
55
|
+
``` ruby
|
50
56
|
class User
|
51
57
|
include ShallowAttributes
|
52
58
|
|
@@ -83,6 +89,31 @@ super_user = SuperUser.new
|
|
83
89
|
user.age = nil # => 0
|
84
90
|
```
|
85
91
|
|
92
|
+
ShallowAttributes doesn't make any assumptions about base classes. There is no need to define
|
93
|
+
default attributes, or even mix ShallowAttributes into the base class:
|
94
|
+
|
95
|
+
``` ruby
|
96
|
+
require 'active_model'
|
97
|
+
|
98
|
+
class Form
|
99
|
+
extend ActiveModel::Naming
|
100
|
+
extend ActiveModel::Translation
|
101
|
+
include ActiveModel::Conversion
|
102
|
+
include ShallowAttributes
|
103
|
+
|
104
|
+
def persisted?
|
105
|
+
false
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class SearchForm < Form
|
110
|
+
attribute :name, String
|
111
|
+
end
|
112
|
+
|
113
|
+
form = SearchForm.new(name: 'Anton')
|
114
|
+
form.name # => "Anton"
|
115
|
+
```
|
116
|
+
|
86
117
|
### Default Values
|
87
118
|
|
88
119
|
``` ruby
|
@@ -103,6 +134,8 @@ class Page
|
|
103
134
|
# default from a method name as symbol
|
104
135
|
attribute :editor_title, String, default: :default_editor_title
|
105
136
|
|
137
|
+
private
|
138
|
+
|
106
139
|
def default_editor_title
|
107
140
|
published ? title : "UNPUBLISHED: #{title}"
|
108
141
|
end
|
@@ -120,6 +153,22 @@ page.reset_attribute(:views) # => 0
|
|
120
153
|
page.views # => 0
|
121
154
|
```
|
122
155
|
|
156
|
+
### Mandatory attributes
|
157
|
+
You can provide `present: true` option for any attribute that will prevent class from initialization
|
158
|
+
if this attribute was not provided:
|
159
|
+
|
160
|
+
``` ruby
|
161
|
+
class CreditCard
|
162
|
+
include ShallowAttributes
|
163
|
+
attribute :number, Integer, present: true
|
164
|
+
attribute :owner, String, present: true
|
165
|
+
end
|
166
|
+
|
167
|
+
card = CreditCard.new(number: 1239342)
|
168
|
+
# => ShallowAttributes::MissingAttributeError: Mandatory attribute "owner" was not provided
|
169
|
+
```
|
170
|
+
|
171
|
+
|
123
172
|
### Embedded Value
|
124
173
|
|
125
174
|
``` ruby
|
@@ -260,7 +309,8 @@ user.attributes
|
|
260
309
|
|
261
310
|
### IMPORTANT note about member coercions
|
262
311
|
|
263
|
-
ShallowAttributes performs coercions only when a value is being assigned. If you mutate the value
|
312
|
+
ShallowAttributes performs coercions only when a value is being assigned. If you mutate the value
|
313
|
+
later on using its own interfaces then coercion won't be triggered.
|
264
314
|
|
265
315
|
Here's an example:
|
266
316
|
|
@@ -310,7 +360,52 @@ user = User.new(name: "Godzilla")
|
|
310
360
|
user.name # => 'Can't tell'
|
311
361
|
```
|
312
362
|
|
313
|
-
### ActiveModel
|
363
|
+
### ActiveModel compatibility
|
364
|
+
|
365
|
+
ShallowAttributes is fully compatible with ActiveModel.
|
366
|
+
|
367
|
+
#### Form object
|
368
|
+
|
369
|
+
``` ruby
|
370
|
+
require 'active_model'
|
371
|
+
|
372
|
+
class SearchForm
|
373
|
+
extend ActiveModel::Naming
|
374
|
+
extend ActiveModel::Translation
|
375
|
+
include ActiveModel::Conversion
|
376
|
+
include ShallowAttributes
|
377
|
+
|
378
|
+
attribute :name, String
|
379
|
+
attribute :service_ids, Array, of: Integer
|
380
|
+
attribute :archived, 'Boolean', default: false
|
381
|
+
|
382
|
+
def persisted?
|
383
|
+
false
|
384
|
+
end
|
385
|
+
|
386
|
+
def results
|
387
|
+
# ...
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
class SearchesController < ApplicationController
|
392
|
+
def index
|
393
|
+
search_params = params.require(:search_form).permit(...)
|
394
|
+
@search_form = SearchForm.new(search_params)
|
395
|
+
end
|
396
|
+
end
|
397
|
+
```
|
398
|
+
|
399
|
+
``` erb
|
400
|
+
<h1>Search</h1>
|
401
|
+
<%= form_for @search_form do |f| %>
|
402
|
+
<%= f.text_field :name %>
|
403
|
+
<%= f.collection_check_boxes :service_ids, Service.all, :id, :name %>
|
404
|
+
<%= f.select :archived, [['Archived', true], ['Not Archived', false]] %>
|
405
|
+
<% end %>
|
406
|
+
```
|
407
|
+
|
408
|
+
#### Validations
|
314
409
|
|
315
410
|
``` ruby
|
316
411
|
require 'active_model'
|
@@ -329,6 +424,26 @@ user.scream = 'hello world!'
|
|
329
424
|
user.valid? # => true
|
330
425
|
```
|
331
426
|
|
427
|
+
### Dry-types
|
428
|
+
You can use dry-types objects as a type for your attribute:
|
429
|
+
```ruby
|
430
|
+
module Types
|
431
|
+
include Dry::Types.module
|
432
|
+
end
|
433
|
+
|
434
|
+
class User
|
435
|
+
include ShallowAttributes
|
436
|
+
|
437
|
+
attribute :name, Types::Coercible::String
|
438
|
+
attribute :age, Types::Coercible::Int
|
439
|
+
attribute :birthday, DateTime
|
440
|
+
end
|
441
|
+
|
442
|
+
user = User.new(name: nil, age: 0)
|
443
|
+
user.name # => ''
|
444
|
+
user.age # => 0
|
445
|
+
```
|
446
|
+
|
332
447
|
## Ruby version support
|
333
448
|
|
334
449
|
ShallowAttributes is [known to work correctly][travis-link] with the following rubies:
|
@@ -352,7 +467,6 @@ to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of
|
|
352
467
|
|
353
468
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
354
469
|
|
355
|
-
|
356
470
|
[doc-link]: http://www.rubydoc.info/github/davydovanton/shallow_attributes/master
|
357
471
|
[virtus-link]: https://github.com/solnic/virtus
|
358
472
|
[fast-attributes-link]: https://github.com/applift/fast_attributes
|
data/bench/allocation.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'memory_profiler'
|
2
|
+
require 'shallow_attributes'
|
3
|
+
|
4
|
+
hash = { addresses: [ { street: 'Street 1/2', city: { name: 'NYC' } }, { street: 'Street 3/2', city: { name: 'Moscow' } } ] }
|
5
|
+
class City
|
6
|
+
include ShallowAttributes
|
7
|
+
attribute :name, String
|
8
|
+
attribute :size, Integer, default: 9000
|
9
|
+
end
|
10
|
+
class Address
|
11
|
+
include ShallowAttributes
|
12
|
+
attribute :street, String
|
13
|
+
attribute :zipcode, String, default: '111111'
|
14
|
+
attribute :city, City
|
15
|
+
end
|
16
|
+
class Person
|
17
|
+
include ShallowAttributes
|
18
|
+
attribute :name, String
|
19
|
+
attribute :address, Address
|
20
|
+
attribute :addresses, Array, of: Address
|
21
|
+
end
|
22
|
+
report = MemoryProfiler.report { 1_000.times { Person.new(hash) } }
|
23
|
+
|
24
|
+
puts report.pretty_print
|
25
|
+
|
26
|
+
# allocated memory by gem
|
27
|
+
# -----------------------------------
|
28
|
+
# 6830520 shallow_attributes/lib
|
29
|
+
#
|
30
|
+
# allocated memory by gem
|
31
|
+
# -----------------------------------
|
32
|
+
# 6310752 shallow_attributes/lib
|
33
|
+
#
|
34
|
+
# allocated memory by gem
|
35
|
+
# -----------------------------------
|
36
|
+
# 5790752 shallow_attributes/lib
|
37
|
+
#
|
38
|
+
# allocated memory by gem
|
39
|
+
# -----------------------------------
|
40
|
+
# 5150752 shallow_attributes/lib
|
41
|
+
#
|
42
|
+
# allocated memory by gem
|
43
|
+
# -----------------------------------
|
44
|
+
# 4950752 shallow_attributes/lib
|
45
|
+
#
|
46
|
+
# allocated memory by gem
|
47
|
+
# -----------------------------------
|
48
|
+
# 4550752 shallow_attributes/lib
|
49
|
+
#
|
50
|
+
# allocated memory by gem
|
51
|
+
# -----------------------------------
|
52
|
+
# 4550520 shallow_attributes/lib
|
53
|
+
#
|
54
|
+
# allocated memory by gem
|
55
|
+
# -----------------------------------
|
56
|
+
# 4470752 shallow_attributes/lib
|
@@ -19,7 +19,7 @@ module ShallowAttributes
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
# Returns hash
|
22
|
+
# Returns hash that contains default values for each attribute
|
23
23
|
#
|
24
24
|
# @private
|
25
25
|
#
|
@@ -30,6 +30,17 @@ module ShallowAttributes
|
|
30
30
|
@default_values ||= {}
|
31
31
|
end
|
32
32
|
|
33
|
+
# Returns hash that contains mandatory attributes
|
34
|
+
#
|
35
|
+
# @private
|
36
|
+
#
|
37
|
+
# @return [Hash] hash with mandatory attributes
|
38
|
+
#
|
39
|
+
# @since 0.10.0
|
40
|
+
def mandatory_attributes
|
41
|
+
@mandatory_attributes ||= {}
|
42
|
+
end
|
43
|
+
|
33
44
|
# Returns all class attributes.
|
34
45
|
#
|
35
46
|
# @example Create new User instance
|
@@ -58,6 +69,7 @@ module ShallowAttributes
|
|
58
69
|
# @option options [Object] :default default value for attribute
|
59
70
|
# @option options [Class] :of class of array elems
|
60
71
|
# @option options [boolean] :allow_nil cast `nil` to integer or float
|
72
|
+
# @option options [boolean] :present raise error if attribute was not provided
|
61
73
|
#
|
62
74
|
# @example Create new User instance
|
63
75
|
# class User
|
@@ -75,6 +87,7 @@ module ShallowAttributes
|
|
75
87
|
options[:default] ||= [] if type == Array
|
76
88
|
|
77
89
|
default_values[name] = options.delete(:default)
|
90
|
+
mandatory_attributes[name] = options.delete(:present)
|
78
91
|
|
79
92
|
initialize_setter(name, type, options)
|
80
93
|
initialize_getter(name)
|
@@ -94,12 +107,14 @@ module ShallowAttributes
|
|
94
107
|
#
|
95
108
|
# @since 0.1.0
|
96
109
|
def initialize_setter(name, type, options)
|
110
|
+
type_class = dry_type?(type) ? type.class : type
|
111
|
+
|
97
112
|
module_eval <<-EOS, __FILE__, __LINE__ + 1
|
98
113
|
def #{name}=(value)
|
99
|
-
@#{name} = if value.is_a?(#{
|
114
|
+
@#{name} = if value.is_a?(#{type_class}) && !value.is_a?(Array)
|
100
115
|
value
|
101
116
|
else
|
102
|
-
|
117
|
+
#{type_casting(type, options)}
|
103
118
|
end
|
104
119
|
|
105
120
|
@attributes[:#{name}] = @#{name}
|
@@ -119,5 +134,42 @@ module ShallowAttributes
|
|
119
134
|
def initialize_getter(name)
|
120
135
|
attr_reader name
|
121
136
|
end
|
137
|
+
|
138
|
+
private
|
139
|
+
|
140
|
+
DRY_TYPE_CLASS = 'Dry::Types'.freeze
|
141
|
+
|
142
|
+
# Check type with dry-type
|
143
|
+
#
|
144
|
+
# @private
|
145
|
+
#
|
146
|
+
# @param [Class] type the class of type
|
147
|
+
#
|
148
|
+
# @return [Bool]
|
149
|
+
#
|
150
|
+
# @since 0.2.0
|
151
|
+
def dry_type?(type)
|
152
|
+
type.class.name.match(DRY_TYPE_CLASS)
|
153
|
+
end
|
154
|
+
|
155
|
+
# Returns string for type casting
|
156
|
+
#
|
157
|
+
# @private
|
158
|
+
#
|
159
|
+
# @param [Class] type the class of type
|
160
|
+
# @param [Hash] options the options
|
161
|
+
#
|
162
|
+
# @return [String]
|
163
|
+
#
|
164
|
+
# @since 0.2.0
|
165
|
+
def type_casting(type, options)
|
166
|
+
if dry_type?(type)
|
167
|
+
# yep, I know that it's terrible line but it was the easily
|
168
|
+
# way to type cast data with dry-types from class method in instance method
|
169
|
+
"ObjectSpace._id2ref(#{type.object_id})[value]"
|
170
|
+
else
|
171
|
+
"ShallowAttributes::Type.coerce(#{type}, value, #{options})"
|
172
|
+
end
|
173
|
+
end
|
122
174
|
end
|
123
175
|
end
|
@@ -6,7 +6,7 @@ module ShallowAttributes
|
|
6
6
|
#
|
7
7
|
# @since 0.1.0
|
8
8
|
module InstanceMethods
|
9
|
-
# Lambda object for
|
9
|
+
# Lambda object for getting attributes hash for a specific
|
10
10
|
# value object.
|
11
11
|
#
|
12
12
|
# @private
|
@@ -14,7 +14,7 @@ module ShallowAttributes
|
|
14
14
|
# @since 0.1.0
|
15
15
|
TO_H_PROC = ->(value) { value.respond_to?(:to_hash) ? value.to_hash : value }
|
16
16
|
|
17
|
-
# Initialize instance object with specific attributes
|
17
|
+
# Initialize an instance object with specific attributes
|
18
18
|
#
|
19
19
|
# @param [Hash] attrs the attributes contained in the class
|
20
20
|
#
|
@@ -37,11 +37,12 @@ module ShallowAttributes
|
|
37
37
|
end
|
38
38
|
define_attributes
|
39
39
|
define_default_attributes
|
40
|
+
define_mandatory_attributes
|
40
41
|
end
|
41
42
|
|
42
43
|
# Returns hash of object attributes
|
43
44
|
#
|
44
|
-
# @example Returns all user
|
45
|
+
# @example Returns all user attributes
|
45
46
|
# class User
|
46
47
|
# include ShallowAttributes
|
47
48
|
# attribute :name, String
|
@@ -68,7 +69,7 @@ module ShallowAttributes
|
|
68
69
|
# @since 0.1.0
|
69
70
|
alias_method :to_hash, :attributes
|
70
71
|
|
71
|
-
#
|
72
|
+
# Attribute values mass-assignment
|
72
73
|
#
|
73
74
|
# @param [Hash] attributes the attributes which will be assignment
|
74
75
|
#
|
@@ -82,22 +83,24 @@ module ShallowAttributes
|
|
82
83
|
# user.attributes = { name: "Ben" }
|
83
84
|
# user.attributes # => { name: "Ben" }
|
84
85
|
#
|
85
|
-
# @return [Hash]
|
86
|
+
# @return [Hash] attributes hash
|
86
87
|
#
|
87
88
|
# @since 0.1.0
|
88
89
|
def attributes=(attributes)
|
89
|
-
|
90
|
+
attributes.each_pair do |key, value|
|
91
|
+
@attributes[key.to_sym] = value
|
92
|
+
end
|
90
93
|
define_attributes
|
91
94
|
end
|
92
95
|
|
93
|
-
#
|
96
|
+
# Reset specific attribute to default value.
|
94
97
|
#
|
95
|
-
# @param [Symbol] attribute the attribute which will be
|
98
|
+
# @param [Symbol] attribute the attribute which will be reset
|
96
99
|
#
|
97
|
-
# @example Reset name
|
100
|
+
# @example Reset name value
|
98
101
|
# class User
|
99
102
|
# include ShallowAttributes
|
100
|
-
# attribute :name, String,
|
103
|
+
# attribute :name, String, default: 'Ben'
|
101
104
|
# end
|
102
105
|
#
|
103
106
|
# user = User.new(name: 'Anton')
|
@@ -115,13 +118,13 @@ module ShallowAttributes
|
|
115
118
|
#
|
116
119
|
# @private
|
117
120
|
#
|
118
|
-
# @param [Hash]
|
119
|
-
# @param [Hash]
|
121
|
+
# @param [Hash] value the new attributes for current object
|
122
|
+
# @param [Hash] _options
|
120
123
|
#
|
121
124
|
# @example Use embedded values
|
122
125
|
# class User
|
123
126
|
# include ShallowAttributes
|
124
|
-
# attribute :name, String,
|
127
|
+
# attribute :name, String, default: 'Ben'
|
125
128
|
# end
|
126
129
|
#
|
127
130
|
# class Post
|
@@ -140,14 +143,14 @@ module ShallowAttributes
|
|
140
143
|
self
|
141
144
|
end
|
142
145
|
|
143
|
-
#
|
146
|
+
# Compare values of two objects
|
144
147
|
#
|
145
148
|
# @param [Object] object the other object
|
146
149
|
#
|
147
|
-
# @example
|
150
|
+
# @example Compare two value objects
|
148
151
|
# class User
|
149
152
|
# include ShallowAttributes
|
150
|
-
# attribute :name, String,
|
153
|
+
# attribute :name, String, default: 'Ben'
|
151
154
|
# end
|
152
155
|
#
|
153
156
|
# user1 = User.new(name: 'Anton')
|
@@ -163,10 +166,10 @@ module ShallowAttributes
|
|
163
166
|
|
164
167
|
# Inspect instance object
|
165
168
|
#
|
166
|
-
# @example
|
169
|
+
# @example Inspect the object
|
167
170
|
# class User
|
168
171
|
# include ShallowAttributes
|
169
|
-
# attribute :name, String,
|
172
|
+
# attribute :name, String, default: 'Ben'
|
170
173
|
# end
|
171
174
|
#
|
172
175
|
# user = User.new(name: 'Anton')
|
@@ -179,9 +182,9 @@ module ShallowAttributes
|
|
179
182
|
"#<#{self.class}#{attributes.map{ |k, v| " #{k}=#{v.inspect}" }.join}>"
|
180
183
|
end
|
181
184
|
|
182
|
-
|
185
|
+
private
|
183
186
|
|
184
|
-
#
|
187
|
+
# Define default values for attributes.
|
185
188
|
#
|
186
189
|
# @private
|
187
190
|
#
|
@@ -195,7 +198,24 @@ module ShallowAttributes
|
|
195
198
|
end
|
196
199
|
end
|
197
200
|
|
198
|
-
#
|
201
|
+
# Define mandatory attributes for object and raise exception
|
202
|
+
# if they were not provided
|
203
|
+
#
|
204
|
+
# @private
|
205
|
+
#
|
206
|
+
# @raise [MissingAttributeError] if attribute was not provided
|
207
|
+
#
|
208
|
+
# @return the object
|
209
|
+
#
|
210
|
+
# @since 0.10.0
|
211
|
+
def define_mandatory_attributes
|
212
|
+
mandatory_attributes.each do |key, value|
|
213
|
+
next unless @attributes[key].nil? && value
|
214
|
+
raise ShallowAttributes::MissingAttributeError, %(Mandatory attribute "#{key}" was not provided)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
# Define attributes from `@attributes` instance value.
|
199
219
|
#
|
200
220
|
# @private
|
201
221
|
#
|
@@ -208,13 +228,13 @@ module ShallowAttributes
|
|
208
228
|
end
|
209
229
|
end
|
210
230
|
|
211
|
-
#
|
212
|
-
#
|
231
|
+
# Returns default value for specific attribute. Default values hash
|
232
|
+
# is taken from class getter `default_values`.
|
213
233
|
#
|
214
234
|
# @private
|
215
235
|
#
|
216
236
|
# @return [nil] if default value not defined
|
217
|
-
# @return [Object] if default value defined
|
237
|
+
# @return [Object] if default value is defined
|
218
238
|
#
|
219
239
|
# @since 0.1.0
|
220
240
|
def default_value_for(attribute)
|
@@ -224,7 +244,7 @@ module ShallowAttributes
|
|
224
244
|
when Proc
|
225
245
|
value.call(self, attribute)
|
226
246
|
when Symbol, String
|
227
|
-
|
247
|
+
respond_to?(value, true) ? send(value) : value
|
228
248
|
else
|
229
249
|
value
|
230
250
|
end
|
@@ -240,5 +260,16 @@ module ShallowAttributes
|
|
240
260
|
def default_values
|
241
261
|
@default_values ||= self.class.default_values
|
242
262
|
end
|
263
|
+
|
264
|
+
# Returns hash of mandatory class attributes
|
265
|
+
#
|
266
|
+
# @private
|
267
|
+
#
|
268
|
+
# @return [Hash]
|
269
|
+
#
|
270
|
+
# @since 0.10.0
|
271
|
+
def mandatory_attributes
|
272
|
+
@mandatory_attributes ||= self.class.mandatory_attributes
|
273
|
+
end
|
243
274
|
end
|
244
275
|
end
|
@@ -18,7 +18,7 @@ module ShallowAttributes
|
|
18
18
|
# ShallowAttributes::Type::Array.new.coerce([1, 2], String)
|
19
19
|
# # => ['1', '2']
|
20
20
|
#
|
21
|
-
# @raise [InvalidValueError] if
|
21
|
+
# @raise [InvalidValueError] if value is not an Array
|
22
22
|
#
|
23
23
|
# @return [Array]
|
24
24
|
#
|
@@ -27,8 +27,16 @@ module ShallowAttributes
|
|
27
27
|
unless values.is_a? ::Array
|
28
28
|
raise ShallowAttributes::Type::InvalidValueError, %(Invalid value "#{values}" for type "Array")
|
29
29
|
end
|
30
|
+
values.map! do |value|
|
31
|
+
ShallowAttributes::Type.coerce(item_klass(options[:of]), value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
30
36
|
|
31
|
-
|
37
|
+
def item_klass(klass)
|
38
|
+
return klass unless klass.is_a? ::String
|
39
|
+
Object.const_get(klass)
|
32
40
|
end
|
33
41
|
end
|
34
42
|
end
|
@@ -25,7 +25,7 @@ module ShallowAttributes
|
|
25
25
|
# @private
|
26
26
|
#
|
27
27
|
# @param [Object] value
|
28
|
-
# @param [Hash]
|
28
|
+
# @param [Hash] _options
|
29
29
|
#
|
30
30
|
# @example Convert integer to boolean value
|
31
31
|
# ShallowAttributes::Type::Boolean.new.coerce(1)
|
@@ -34,7 +34,7 @@ module ShallowAttributes
|
|
34
34
|
# ShallowAttributes::Type::Boolean.new.coerce(0)
|
35
35
|
# # => false
|
36
36
|
#
|
37
|
-
# @raise [InvalidValueError] if
|
37
|
+
# @raise [InvalidValueError] if value is not included in true and false arrays
|
38
38
|
#
|
39
39
|
# @return [boolean]
|
40
40
|
#
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
1
3
|
module ShallowAttributes
|
2
4
|
module Type
|
3
5
|
# Abstract class for typecast object to DateTime type.
|
@@ -11,13 +13,13 @@ module ShallowAttributes
|
|
11
13
|
# @private
|
12
14
|
#
|
13
15
|
# @param [Object] value
|
14
|
-
# @param [Hash]
|
16
|
+
# @param [Hash] _options
|
15
17
|
#
|
16
18
|
# @example Convert integer to datetime value
|
17
19
|
# ShallowAttributes::Type::DateTime.new.coerce('Thu Nov 29 14:33:20 GMT 2001')
|
18
20
|
# # => '2001-11-29T14:33:20+00:00'
|
19
21
|
#
|
20
|
-
# @raise [InvalidValueError] if
|
22
|
+
# @raise [InvalidValueError] if value is not a string
|
21
23
|
#
|
22
24
|
# @return [DateTime]
|
23
25
|
#
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module ShallowAttributes
|
2
2
|
module Type
|
3
|
-
# This class
|
3
|
+
# This class is needed to change object type to Float.
|
4
4
|
#
|
5
5
|
# @abstract
|
6
6
|
#
|
@@ -11,14 +11,14 @@ module ShallowAttributes
|
|
11
11
|
# @private
|
12
12
|
#
|
13
13
|
# @param [Object] value
|
14
|
-
# @param [Hash]
|
14
|
+
# @param [Hash] options
|
15
15
|
# @option options [boolean] :allow_nil cast `nil` to integer or float
|
16
16
|
#
|
17
17
|
# @example Convert string to float value
|
18
18
|
# ShallowAttributes::Type::Float.new.coerce('2001')
|
19
19
|
# # => 2001.0
|
20
20
|
#
|
21
|
-
# @raise [InvalidValueError] if
|
21
|
+
# @raise [InvalidValueError] if value is invalid
|
22
22
|
#
|
23
23
|
# @return [Float]
|
24
24
|
#
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module ShallowAttributes
|
2
2
|
module Type
|
3
|
-
# This class
|
3
|
+
# This class changes object to Integer.
|
4
4
|
#
|
5
5
|
# @abstract
|
6
6
|
#
|
@@ -11,14 +11,14 @@ module ShallowAttributes
|
|
11
11
|
# @private
|
12
12
|
#
|
13
13
|
# @param [Object] value
|
14
|
-
# @param [Hash]
|
14
|
+
# @param [Hash] options
|
15
15
|
# @option options [boolean] :allow_nil cast `nil` to integer or float
|
16
16
|
#
|
17
17
|
# @example Convert sting to integer value
|
18
18
|
# ShallowAttributes::Type::Integer.new.coerce('2001')
|
19
19
|
# # => 2001
|
20
20
|
#
|
21
|
-
# @raise [InvalidValueError] if
|
21
|
+
# @raise [InvalidValueError] if value is invalid
|
22
22
|
#
|
23
23
|
# @return [Integer]
|
24
24
|
#
|
@@ -11,9 +11,9 @@ module ShallowAttributes
|
|
11
11
|
# @private
|
12
12
|
#
|
13
13
|
# @param [Object] value
|
14
|
-
# @param [Hash]
|
14
|
+
# @param [Hash] _options
|
15
15
|
#
|
16
|
-
# @example Convert
|
16
|
+
# @example Convert integer to string value
|
17
17
|
# ShallowAttributes::Type::String.new.coerce(2001)
|
18
18
|
# # => '2001'
|
19
19
|
#
|
@@ -11,13 +11,13 @@ module ShallowAttributes
|
|
11
11
|
# @private
|
12
12
|
#
|
13
13
|
# @param [Object] value
|
14
|
-
# @param [Hash]
|
14
|
+
# @param [Hash] _options
|
15
15
|
#
|
16
16
|
# @example Convert string to Time value
|
17
17
|
# ShallowAttributes::Type::Time.new.coerce('Thu Nov 29 14:33:20 GMT 2001')
|
18
18
|
# # => '2001-11-29 14:33:20 +0000'
|
19
19
|
#
|
20
|
-
# @raise [InvalidValueError] if
|
20
|
+
# @raise [InvalidValueError] if value is not a sting or an integer
|
21
21
|
#
|
22
22
|
# @return [Time]
|
23
23
|
#
|
@@ -7,11 +7,11 @@ require 'shallow_attributes/type/string'
|
|
7
7
|
require 'shallow_attributes/type/time'
|
8
8
|
|
9
9
|
module ShallowAttributes
|
10
|
-
# Namespace for
|
10
|
+
# Namespace for standard type classes
|
11
11
|
#
|
12
12
|
# @since 0.1.0
|
13
13
|
module Type
|
14
|
-
# Error class for
|
14
|
+
# Error class for invalid value types
|
15
15
|
#
|
16
16
|
# @since 0.1.0
|
17
17
|
class InvalidValueError < TypeError
|
@@ -37,7 +37,7 @@ module ShallowAttributes
|
|
37
37
|
# @private
|
38
38
|
#
|
39
39
|
# @param [Class] type the type class object
|
40
|
-
# @param [Object] value the value that should be
|
40
|
+
# @param [Object] value the value that should be coerced to the necessary type
|
41
41
|
# @param [Hash] options the options to create a message with.
|
42
42
|
# @option options [String] :of The type of array
|
43
43
|
# @option options [boolean] :allow_nil cast `nil` to integer or float
|
@@ -63,7 +63,7 @@ module ShallowAttributes
|
|
63
63
|
#
|
64
64
|
# @private
|
65
65
|
#
|
66
|
-
# @param [Class]
|
66
|
+
# @param [Class] klass the type class object
|
67
67
|
#
|
68
68
|
# @example Returns Sting type class
|
69
69
|
# ShallowAttributes::Type.instance_for(String)
|
data/lib/shallow_attributes.rb
CHANGED
@@ -9,13 +9,18 @@ require 'shallow_attributes/version'
|
|
9
9
|
module ShallowAttributes
|
10
10
|
include InstanceMethods
|
11
11
|
|
12
|
+
# Error class for mandatory arguments that were not provided
|
13
|
+
#
|
14
|
+
# @since 0.10.0
|
15
|
+
class MissingAttributeError < TypeError; end
|
16
|
+
|
12
17
|
# Including ShallowAttributes class methods to specific class
|
13
18
|
#
|
14
19
|
# @private
|
15
20
|
#
|
16
21
|
# @param [Class] base the class containing class methods
|
17
22
|
#
|
18
|
-
# @return [Class] class for
|
23
|
+
# @return [Class] class for including ShallowAttributes gem
|
19
24
|
#
|
20
25
|
# @since 0.1.0
|
21
26
|
def self.included(base)
|
data/shallow_attributes.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shallow_attributes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anton Davydov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-11-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '5.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: dry-types
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.11'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.11'
|
55
69
|
description: Attributes for Plain Old Ruby Objects
|
56
70
|
email:
|
57
71
|
- antondavydov.o@gmail.com
|
@@ -67,6 +81,7 @@ files:
|
|
67
81
|
- LICENSE.txt
|
68
82
|
- README.md
|
69
83
|
- Rakefile
|
84
|
+
- bench/allocation.rb
|
70
85
|
- lib/shallow_attributes.rb
|
71
86
|
- lib/shallow_attributes/class_methods.rb
|
72
87
|
- lib/shallow_attributes/instance_methods.rb
|
@@ -100,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
115
|
version: '0'
|
101
116
|
requirements: []
|
102
117
|
rubyforge_project:
|
103
|
-
rubygems_version: 2.
|
118
|
+
rubygems_version: 2.6.13
|
104
119
|
signing_key:
|
105
120
|
specification_version: 4
|
106
121
|
summary: Attributes for Plain Old Ruby Objects
|