shallow_attributes 0.9.2 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Build Status](https://travis-ci.org/davydovanton/shallow_attributes.svg?branch=master)](https://travis-ci.org/davydovanton/shallow_attributes)
|
3
4
|
[![Code Climate](https://codeclimate.com/github/davydovanton/shallow_attributes/badges/gpa.svg)](https://codeclimate.com/github/davydovanton/shallow_attributes)
|
4
5
|
[![Coverage Status](https://coveralls.io/repos/github/davydovanton/shallow_attributes/badge.svg?branch=master)](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
|