anima 0.2.0 → 0.3.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 +4 -4
- data/.rubocop.yml +3 -3
- data/.travis.yml +5 -22
- data/Changelog.md +14 -0
- data/Gemfile +5 -7
- data/README.md +30 -21
- data/Rakefile +9 -1
- data/anima.gemspec +6 -4
- data/circle.yml +3 -2
- data/config/flay.yml +1 -1
- data/config/flog.yml +1 -1
- data/config/mutant.yml +1 -0
- data/config/reek.yml +10 -5
- data/config/rubocop.yml +83 -27
- data/lib/anima.rb +73 -17
- data/lib/anima/attribute.rb +10 -8
- data/lib/anima/error.rb +8 -23
- data/spec/integration/simple_spec.rb +4 -5
- data/spec/spec_helper.rb +0 -3
- data/spec/unit/anima/attribute_spec.rb +14 -19
- data/spec/unit/anima/error_spec.rb +10 -16
- data/spec/unit/anima_spec.rb +41 -6
- metadata +20 -25
- data/Gemfile.devtools +0 -69
- data/lib/anima/builder.rb +0 -130
- data/lib/anima/update.rb +0 -30
- data/spec/unit/anima/update_spec.rb +0 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d3d1052ef69a252eba9f680d8918977ebe21957
|
4
|
+
data.tar.gz: 95726462b39f8b85f7706c5415369eb0e141e48d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 320e39521765b3c969063d635b90c3fc51927b2ac9f1fb46e4c13b02f56a539fb3bf1d57fd8f05742a7fe2b83143c0b3d91c3b3e037a4b142cb3341c7907f9cb
|
7
|
+
data.tar.gz: 73e0f2c5c9dc9901dc0c0ce04b899a3c23c5587ff144794b303e53eff9da2bc13d09ca99ea43ff9600805cc8f3ff58c991ebfe66b1eeb9cf8e9c9a796630e29f
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
@@ -3,26 +3,9 @@ cache: bundler
|
|
3
3
|
bundler_args: --without yard guard benchmarks
|
4
4
|
script: "bundle exec rake ci:metrics"
|
5
5
|
rvm:
|
6
|
-
- 1
|
7
|
-
- 2.
|
8
|
-
- 2.1.0-rc1
|
9
|
-
- ruby-head
|
10
|
-
- rbx
|
6
|
+
- '2.1'
|
7
|
+
- '2.2'
|
11
8
|
matrix:
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
- rvm: jruby-20mode
|
16
|
-
env: JRUBY_OPTS="$JRUBY_OPTS --debug" # for simplecov
|
17
|
-
- rvm: jruby-head
|
18
|
-
env: JRUBY_OPTS="$JRUBY_OPTS --debug" # for simplecov
|
19
|
-
allow_failures:
|
20
|
-
- rvm: 2.1.0-rc1
|
21
|
-
- rvm: ruby-head
|
22
|
-
fast_finish: true
|
23
|
-
notifications:
|
24
|
-
irc:
|
25
|
-
channels:
|
26
|
-
- irc.freenode.org#rom-rb
|
27
|
-
on_success: never
|
28
|
-
on_failure: change
|
9
|
+
allowed_failures:
|
10
|
+
- jruby # Travis jruby does not run in >= 2.1 ruby yet
|
11
|
+
- rbx # segfault
|
data/Changelog.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
# v0.3.0 2015-xx-xx
|
2
|
+
|
3
|
+
Changes:
|
4
|
+
|
5
|
+
* Drop support for ruby < 2.1
|
6
|
+
* Drop support for Anima::Update
|
7
|
+
* Add #with as a replacement that is active by default [#13]
|
8
|
+
|
9
|
+
# v0.2.1 2014-04-10
|
10
|
+
|
11
|
+
Changes:
|
12
|
+
|
13
|
+
* Require ruby version >= 1.9.3 in gemspec.
|
14
|
+
|
1
15
|
# v0.2.0 2014-01-13
|
2
16
|
|
3
17
|
Breaking changes:
|
data/Gemfile
CHANGED
@@ -1,11 +1,9 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
1
|
source 'https://rubygems.org'
|
4
2
|
|
5
3
|
gemspec
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
gem 'devtools', git: 'https://github.com/rom-rb/devtools.git'
|
6
|
+
gem 'mutant', git: 'https://github.com/mbj/mutant.git',
|
7
|
+
branch: 'fix/anima-update'
|
8
|
+
gem 'morpher', git: 'https://github.com/mbj/morpher.git',
|
9
|
+
branch: 'fix/upgrade-anima'
|
data/README.md
CHANGED
@@ -4,6 +4,7 @@ anima
|
|
4
4
|
[](http://travis-ci.org/mbj/anima)
|
5
5
|
[](https://gemnasium.com/mbj/anima)
|
6
6
|
[](https://codeclimate.com/github/mbj/anima)
|
7
|
+
[](https://rubygems.org/gems/anima)
|
7
8
|
|
8
9
|
Simple library to declare read only attributes on value-objects that are initialized via attributes hash.
|
9
10
|
|
@@ -15,7 +16,9 @@ Install the gem `anima` via your preferred method.
|
|
15
16
|
Examples
|
16
17
|
--------
|
17
18
|
|
18
|
-
```
|
19
|
+
```ruby
|
20
|
+
require 'anima'
|
21
|
+
|
19
22
|
# Definition
|
20
23
|
class Person
|
21
24
|
include Anima.new(:salutation, :firstname, :lastname)
|
@@ -23,28 +26,30 @@ end
|
|
23
26
|
|
24
27
|
# Every day operation
|
25
28
|
a = Person.new(
|
26
|
-
:
|
27
|
-
:
|
28
|
-
:
|
29
|
+
salutation: 'Mr',
|
30
|
+
firstname: 'Markus',
|
31
|
+
lastname: 'Schirp'
|
29
32
|
)
|
30
33
|
|
34
|
+
# Returns expected values
|
31
35
|
a.salutation # => "Mr"
|
32
36
|
a.firstname # => "Markus"
|
33
37
|
a.lastname # => "Schirp"
|
34
|
-
a.frozen? # =>
|
38
|
+
a.frozen? # => false
|
35
39
|
|
36
40
|
b = Person.new(
|
37
|
-
:
|
38
|
-
:
|
39
|
-
:
|
41
|
+
salutation: 'Mr',
|
42
|
+
firstname: 'John',
|
43
|
+
lastname: 'Doe'
|
40
44
|
)
|
41
45
|
|
42
|
-
|
43
|
-
:
|
44
|
-
:
|
45
|
-
:
|
46
|
+
c = Person.new(
|
47
|
+
salutation: 'Mr',
|
48
|
+
firstname: 'Markus',
|
49
|
+
lastname: 'Schirp'
|
46
50
|
)
|
47
51
|
|
52
|
+
# Equality based on attributes
|
48
53
|
a == b # => false
|
49
54
|
a.eql?(b) # => false
|
50
55
|
a.equal?(b) # => false
|
@@ -53,21 +58,25 @@ a == c # => true
|
|
53
58
|
a.eql?(c) # => true
|
54
59
|
a.equal?(c) # => false
|
55
60
|
|
56
|
-
# Functional updates
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
d = b.update(
|
62
|
-
:salutation => 'Mrs',
|
63
|
-
:firstname => 'Sue',
|
61
|
+
# Functional-style updates
|
62
|
+
d = b.with(
|
63
|
+
salutation: 'Mrs',
|
64
|
+
firstname: 'Sue',
|
64
65
|
)
|
65
66
|
|
66
67
|
# It returns copies, no inplace modification
|
67
68
|
d.equal?(b) # => false
|
68
69
|
|
69
70
|
# Hash representation
|
70
|
-
d.to_h # => { :
|
71
|
+
d.to_h # => { salutation: 'Mrs', firstname: 'Sue', lastname: 'Doe' }
|
72
|
+
|
73
|
+
# Disallows initialization with incompatible attributes
|
74
|
+
|
75
|
+
Person.new(
|
76
|
+
# :saluatation key missing
|
77
|
+
"firstname" => "Markus", # does NOT coerce this by intention
|
78
|
+
:lastname => "Schirp"
|
79
|
+
) # raises Anima::Error with message "Person attributes missing: [:salutation, :firstname], unknown: ["firstname"]
|
71
80
|
```
|
72
81
|
|
73
82
|
Credits
|
data/Rakefile
CHANGED
@@ -6,6 +6,14 @@ task('metrics:mutant').clear
|
|
6
6
|
|
7
7
|
namespace :metrics do
|
8
8
|
task :mutant => :coverage do
|
9
|
-
|
9
|
+
system(*%w[
|
10
|
+
bundle exec mutant
|
11
|
+
--include lib
|
12
|
+
--require anima
|
13
|
+
--use rspec
|
14
|
+
--zombie
|
15
|
+
--
|
16
|
+
Anima*
|
17
|
+
]) or fail "Mutant task failed"
|
10
18
|
end
|
11
19
|
end
|
data/anima.gemspec
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
|
-
s.name
|
5
|
-
s.version = '0.
|
4
|
+
s.name = 'anima'
|
5
|
+
s.version = '0.3.0'
|
6
6
|
|
7
7
|
s.authors = ['Markus Schirp']
|
8
8
|
s.email = 'mbj@schirp-dso.com'
|
@@ -15,7 +15,9 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.require_paths = %w(lib)
|
16
16
|
s.extra_rdoc_files = %w(README.md)
|
17
17
|
|
18
|
-
s.
|
19
|
-
|
18
|
+
s.required_ruby_version = '>= 2.1.0'
|
19
|
+
|
20
|
+
s.add_dependency('adamantium', '~> 0.2')
|
21
|
+
s.add_dependency('equalizer', '~> 0.0.11')
|
20
22
|
s.add_dependency('abstract_type', '~> 0.0.7')
|
21
23
|
end
|
data/circle.yml
CHANGED
data/config/flay.yml
CHANGED
data/config/flog.yml
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
---
|
2
|
-
threshold: 9
|
2
|
+
threshold: 11.9
|
data/config/mutant.yml
CHANGED
data/config/reek.yml
CHANGED
@@ -22,7 +22,8 @@ UncommunicativeMethodName:
|
|
22
22
|
- !ruby/regexp /[A-Z]/
|
23
23
|
LongParameterList:
|
24
24
|
max_params: 2 # TODO: decrease max_params to 2
|
25
|
-
exclude:
|
25
|
+
exclude:
|
26
|
+
- Anima::Error#initialize # 3 params
|
26
27
|
enabled: true
|
27
28
|
overrides: {}
|
28
29
|
FeatureEnvy:
|
@@ -35,9 +36,10 @@ ClassVariable:
|
|
35
36
|
BooleanParameter:
|
36
37
|
exclude: []
|
37
38
|
enabled: true
|
39
|
+
# Buggy like hell
|
38
40
|
IrresponsibleModule:
|
39
41
|
exclude: []
|
40
|
-
enabled:
|
42
|
+
enabled: false
|
41
43
|
UncommunicativeModuleName:
|
42
44
|
accept: []
|
43
45
|
exclude: []
|
@@ -49,8 +51,7 @@ NestedIterators:
|
|
49
51
|
ignore_iterators: []
|
50
52
|
exclude:
|
51
53
|
- Anima::Attribute#define_reader # 2 levels
|
52
|
-
- Anima
|
53
|
-
- Anima::Builder#define_attribute_readers # 2 levels
|
54
|
+
- Anima#included # 2 levels
|
54
55
|
enabled: true
|
55
56
|
max_allowed_nesting: 1
|
56
57
|
TooManyStatements:
|
@@ -64,7 +65,8 @@ DuplicateMethodCall:
|
|
64
65
|
max_calls: 1
|
65
66
|
UtilityFunction:
|
66
67
|
max_helper_calls: 1
|
67
|
-
exclude:
|
68
|
+
exclude:
|
69
|
+
- Anima::Error#initialize # false positive, calls super
|
68
70
|
enabled: true
|
69
71
|
Attribute:
|
70
72
|
exclude: []
|
@@ -93,3 +95,6 @@ LongYieldList:
|
|
93
95
|
max_params: 1
|
94
96
|
exclude: []
|
95
97
|
enabled: true
|
98
|
+
# Thats the whole point of this lib, oOo.
|
99
|
+
ModuleInitialize:
|
100
|
+
enabled: false
|
data/config/rubocop.yml
CHANGED
@@ -16,6 +16,9 @@ CollectionMethods:
|
|
16
16
|
inject: 'reduce'
|
17
17
|
find: 'detect'
|
18
18
|
find_all: 'select'
|
19
|
+
Exclude:
|
20
|
+
# The Pathname#find method is mistakenly identified as Enumberable#find
|
21
|
+
- lib/tasks/assets_precompile_nodigest.rake
|
19
22
|
|
20
23
|
# Do not force public/protected/private keyword to be indented at the same
|
21
24
|
# level as the def keyword. My personal preference is to outdent these keywords
|
@@ -26,38 +29,20 @@ CollectionMethods:
|
|
26
29
|
AccessModifierIndentation:
|
27
30
|
Enabled: false
|
28
31
|
|
29
|
-
MethodLength:
|
30
|
-
CountComments: false
|
31
|
-
Max: 17 # TODO: Bring down to 10
|
32
|
-
|
33
|
-
RegexpLiteral: # I do not agree %r(\A) is more readable than /\A/
|
34
|
-
Enabled: false
|
35
|
-
|
36
|
-
Eval:
|
37
|
-
Enabled: false # Mutant must use Kernel#eval to inject mutated source
|
38
|
-
|
39
32
|
# Limit line length
|
40
33
|
LineLength:
|
41
|
-
Max:
|
34
|
+
Max: 79
|
42
35
|
|
43
36
|
# Disable documentation checking until a class needs to be documented once
|
44
37
|
Documentation:
|
45
38
|
Enabled: false
|
46
39
|
|
47
|
-
# Do not
|
48
|
-
|
49
|
-
Enabled: false
|
50
|
-
|
51
|
-
# Mutant needs to define methods like def bar; end in specs
|
52
|
-
Semicolon:
|
53
|
-
Enabled: false
|
54
|
-
|
55
|
-
# Mutant needs to define multiple methods on same line in specs
|
56
|
-
EmptyLineBetweenDefs:
|
40
|
+
# Do not always use &&/|| instead of and/or.
|
41
|
+
AndOr:
|
57
42
|
Enabled: false
|
58
43
|
|
59
|
-
#
|
60
|
-
|
44
|
+
# Do not favor modifier if/unless usage when you have a single-line body
|
45
|
+
IfUnlessModifier:
|
61
46
|
Enabled: false
|
62
47
|
|
63
48
|
# Allow case equality operator (in limited use within the specs)
|
@@ -72,10 +57,81 @@ ConstantName:
|
|
72
57
|
TrivialAccessors:
|
73
58
|
Enabled: false
|
74
59
|
|
75
|
-
#
|
76
|
-
|
60
|
+
# Allow empty lines around class body
|
61
|
+
EmptyLinesAroundClassBody:
|
62
|
+
Enabled: false
|
63
|
+
|
64
|
+
# Allow empty lines around module body
|
65
|
+
EmptyLinesAroundModuleBody:
|
66
|
+
Enabled: false
|
67
|
+
|
68
|
+
# Allow empty lines around block body
|
69
|
+
EmptyLinesAroundBlockBody:
|
70
|
+
Enabled: false
|
71
|
+
|
72
|
+
# Allow multiple line operations to not require indentation
|
73
|
+
MultilineOperationIndentation:
|
74
|
+
Enabled: false
|
75
|
+
|
76
|
+
# Prefer String#% over Kernel#sprintf
|
77
|
+
FormatString:
|
78
|
+
Enabled: false
|
79
|
+
|
80
|
+
# Use square brackets for literal Array objects
|
81
|
+
PercentLiteralDelimiters:
|
82
|
+
PreferredDelimiters:
|
83
|
+
'%': '{}'
|
84
|
+
'%i': '[]'
|
85
|
+
'%q': ()
|
86
|
+
'%Q': ()
|
87
|
+
'%r': '{}'
|
88
|
+
'%s': ()
|
89
|
+
'%w': '[]'
|
90
|
+
'%W': '[]'
|
91
|
+
'%x': ()
|
92
|
+
|
93
|
+
# Use %i[...] for arrays of symbols
|
94
|
+
SymbolArray:
|
95
|
+
Enabled: true
|
96
|
+
|
97
|
+
# Align if/else blocks with the variable assignment
|
98
|
+
EndAlignment:
|
99
|
+
AlignWith: variable
|
100
|
+
|
101
|
+
# Do not always align parameters when it is easier to read
|
102
|
+
AlignParameters:
|
103
|
+
Exclude:
|
104
|
+
- spec/**/*_spec.rb
|
105
|
+
|
106
|
+
# Prefer #kind_of? over #is_a?
|
107
|
+
ClassCheck:
|
108
|
+
EnforcedStyle: kind_of?
|
109
|
+
|
110
|
+
# Do not prefer double quotes to be used when %q or %Q is more appropriate
|
111
|
+
UnneededPercentQ:
|
112
|
+
Enabled: false
|
113
|
+
|
114
|
+
# Allow a maximum ABC score
|
115
|
+
Metrics/AbcSize:
|
116
|
+
Max: 21.02
|
117
|
+
|
118
|
+
# Do not prefer lambda.call(...) over lambda.(...)
|
119
|
+
LambdaCall:
|
120
|
+
Enabled: false
|
121
|
+
|
122
|
+
# Buggy cop, returns false positive for our code base
|
123
|
+
NonLocalExitFromIterator:
|
124
|
+
Enabled: false
|
125
|
+
|
126
|
+
# To allow alignment of similar expressions we want to allow more than one
|
127
|
+
# space around operators:
|
128
|
+
#
|
129
|
+
# let(:a) { bar + something }
|
130
|
+
# let(:b) { foobar + something }
|
131
|
+
#
|
132
|
+
SpaceAroundOperators:
|
77
133
|
Enabled: false
|
78
134
|
|
79
|
-
#
|
80
|
-
|
135
|
+
# We use parallel assignments with great success
|
136
|
+
ParallelAssignment:
|
81
137
|
Enabled: false
|
data/lib/anima.rb
CHANGED
@@ -31,8 +31,8 @@ class Anima < Module
|
|
31
31
|
# @return [Anima]
|
32
32
|
#
|
33
33
|
# @example
|
34
|
-
# anima = Anima.new(:foo
|
35
|
-
# anima.add(:
|
34
|
+
# anima = Anima.new(:foo)
|
35
|
+
# anima.add(:bar) # equals Anima.new(:foo, :bar)
|
36
36
|
#
|
37
37
|
# @api private
|
38
38
|
#
|
@@ -45,7 +45,7 @@ class Anima < Module
|
|
45
45
|
# @return [Anima]
|
46
46
|
#
|
47
47
|
# @example
|
48
|
-
# anima = Anima.new(:foo)
|
48
|
+
# anima = Anima.new(:foo, :bar)
|
49
49
|
# anima.remove(:bar) # equals Anima.new(:foo)
|
50
50
|
#
|
51
51
|
# @api public
|
@@ -90,16 +90,62 @@ class Anima < Module
|
|
90
90
|
# @api private
|
91
91
|
#
|
92
92
|
def initialize_instance(object, attribute_hash)
|
93
|
-
assert_known_attributes(object, attribute_hash)
|
93
|
+
assert_known_attributes(object.class, attribute_hash)
|
94
94
|
attributes.each do |attribute|
|
95
95
|
attribute.load(object, attribute_hash)
|
96
96
|
end
|
97
97
|
self
|
98
98
|
end
|
99
99
|
|
100
|
+
# Static instance methods for anima infected classes
|
101
|
+
module InstanceMethods
|
102
|
+
# Initialize an anima infected object
|
103
|
+
#
|
104
|
+
# @param [#to_h] attributes
|
105
|
+
# a hash that matches anima defined attributes
|
106
|
+
#
|
107
|
+
# @return [undefined]
|
108
|
+
#
|
109
|
+
# @api public
|
110
|
+
def initialize(attributes)
|
111
|
+
self.class.anima.initialize_instance(self, attributes)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Return a hash representation of an anima infected object
|
115
|
+
#
|
116
|
+
# @return [Hash]
|
117
|
+
#
|
118
|
+
# @api public
|
119
|
+
def to_h
|
120
|
+
self.class.anima.attributes_hash(self)
|
121
|
+
end
|
122
|
+
|
123
|
+
# Return updated instance
|
124
|
+
#
|
125
|
+
# @example
|
126
|
+
# klass = Class.new do
|
127
|
+
# include Anima.new(:foo, :bar)
|
128
|
+
# end
|
129
|
+
#
|
130
|
+
# foo = klass.new(:foo => 1, :bar => 2)
|
131
|
+
# updated = foo.with(:foo => 3)
|
132
|
+
# updated.foo # => 3
|
133
|
+
# updated.bar # => 2
|
134
|
+
#
|
135
|
+
# @param [Hash] attributes
|
136
|
+
#
|
137
|
+
# @return [Anima]
|
138
|
+
#
|
139
|
+
# @api private
|
140
|
+
#
|
141
|
+
def with(attributes)
|
142
|
+
self.class.new(to_h.update(attributes))
|
143
|
+
end
|
144
|
+
end # InstanceMethods
|
145
|
+
|
100
146
|
private
|
101
147
|
|
102
|
-
#
|
148
|
+
# Infect the instance with anima
|
103
149
|
#
|
104
150
|
# @param [Class, Module] scope
|
105
151
|
#
|
@@ -108,28 +154,41 @@ class Anima < Module
|
|
108
154
|
# @api private
|
109
155
|
#
|
110
156
|
def included(descendant)
|
111
|
-
|
157
|
+
descendant.instance_exec(self, attribute_names) do |anima, names|
|
158
|
+
# Define anima method
|
159
|
+
define_singleton_method(:anima) { anima }
|
160
|
+
|
161
|
+
# Define instance methods
|
162
|
+
include InstanceMethods
|
163
|
+
|
164
|
+
# Define attribute readers
|
165
|
+
attr_reader(*names)
|
166
|
+
|
167
|
+
# Define equalizer
|
168
|
+
include Equalizer.new(*names)
|
169
|
+
end
|
112
170
|
end
|
113
171
|
|
114
172
|
# Fail unless keys in +attribute_hash+ matches #attribute_names
|
115
173
|
#
|
116
|
-
# @param [
|
117
|
-
# the
|
174
|
+
# @param [Class] klass
|
175
|
+
# the class being initialized
|
118
176
|
#
|
119
177
|
# @param [Hash] attribute_hash
|
120
178
|
# the attributes to initialize +object+ with
|
121
179
|
#
|
122
180
|
# @return [undefined]
|
123
181
|
#
|
124
|
-
# @raise [Error
|
182
|
+
# @raise [Error]
|
125
183
|
#
|
126
184
|
# @api private
|
127
|
-
def assert_known_attributes(
|
128
|
-
|
185
|
+
def assert_known_attributes(klass, attribute_hash)
|
186
|
+
keys = attribute_hash.keys
|
129
187
|
|
130
|
-
|
131
|
-
|
132
|
-
|
188
|
+
unknown = keys - attribute_names
|
189
|
+
missing = attribute_names - keys
|
190
|
+
|
191
|
+
fail Error.new(klass, missing, unknown) if unknown.any? || missing.any?
|
133
192
|
end
|
134
193
|
|
135
194
|
# Return new instance
|
@@ -143,10 +202,7 @@ class Anima < Module
|
|
143
202
|
def new(attributes)
|
144
203
|
self.class.new(*attributes)
|
145
204
|
end
|
146
|
-
|
147
205
|
end # Anima
|
148
206
|
|
149
|
-
require 'anima/builder'
|
150
207
|
require 'anima/error'
|
151
208
|
require 'anima/attribute'
|
152
|
-
require 'anima/update'
|
data/lib/anima/attribute.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
class Anima
|
4
|
-
|
5
4
|
# An attribute
|
6
5
|
class Attribute
|
7
6
|
include Adamantium::Flat, Equalizer.new(:name)
|
@@ -24,6 +23,14 @@ class Anima
|
|
24
23
|
#
|
25
24
|
attr_reader :name
|
26
25
|
|
26
|
+
# Return instance variable name
|
27
|
+
#
|
28
|
+
# @return [Symbol]
|
29
|
+
#
|
30
|
+
# @api private
|
31
|
+
#
|
32
|
+
attr_reader :instance_variable_name
|
33
|
+
|
27
34
|
# Load attribute
|
28
35
|
#
|
29
36
|
# @param [Object] object
|
@@ -34,11 +41,7 @@ class Anima
|
|
34
41
|
# @api private
|
35
42
|
#
|
36
43
|
def load(object, attributes)
|
37
|
-
|
38
|
-
fail Error::Missing.new(object, attribute_name)
|
39
|
-
end
|
40
|
-
|
41
|
-
set(object, value)
|
44
|
+
set(object, attributes.fetch(name))
|
42
45
|
end
|
43
46
|
|
44
47
|
# Get attribute value from object
|
@@ -63,10 +66,9 @@ class Anima
|
|
63
66
|
# @api private
|
64
67
|
#
|
65
68
|
def set(object, value)
|
66
|
-
object.instance_variable_set(
|
69
|
+
object.instance_variable_set(instance_variable_name, value)
|
67
70
|
|
68
71
|
self
|
69
72
|
end
|
70
|
-
|
71
73
|
end # Attribute
|
72
74
|
end # Anima
|
data/lib/anima/error.rb
CHANGED
@@ -1,39 +1,24 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
class Anima
|
4
|
-
|
5
4
|
# Abstract base class for anima errors
|
6
5
|
class Error < RuntimeError
|
7
|
-
|
8
|
-
|
9
|
-
class Unknown < self
|
10
|
-
end
|
11
|
-
|
12
|
-
# Error for missing attributes
|
13
|
-
class Missing < self
|
14
|
-
end
|
15
|
-
|
16
|
-
include AbstractType
|
17
|
-
|
18
|
-
DOUBLE_COLON = '::'.freeze
|
6
|
+
FORMAT = '%s attributes missing: %s, unknown: %s'.freeze
|
7
|
+
private_constant(*constants(false))
|
19
8
|
|
20
9
|
# Initialize object
|
21
10
|
#
|
22
|
-
# @param [
|
23
|
-
#
|
11
|
+
# @param [Class] klass
|
12
|
+
# the class being initialized
|
13
|
+
# @param [Enumerable<Symbol>] missing
|
14
|
+
# @param [Enumerable<Symbol>] unknown
|
24
15
|
#
|
25
16
|
# @return [undefined]
|
26
17
|
#
|
27
18
|
# @api private
|
28
19
|
#
|
29
|
-
def initialize(
|
30
|
-
super(
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def name
|
36
|
-
self.class.name.split(DOUBLE_COLON).last
|
20
|
+
def initialize(klass, missing, unknown)
|
21
|
+
super(FORMAT % [klass, missing, unknown])
|
37
22
|
end
|
38
23
|
end # Error
|
39
24
|
end # Anima
|
@@ -32,20 +32,19 @@ describe Anima, 'simple integration' do
|
|
32
32
|
|
33
33
|
it 'should raise error' do
|
34
34
|
expect { subject }.to raise_error(
|
35
|
-
Anima::Error
|
36
|
-
'
|
35
|
+
Anima::Error,
|
36
|
+
'TestClass attributes missing: [], unknown: [:extra]'
|
37
37
|
)
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
41
|
context 'when instantiated with missing attributes' do
|
42
|
-
|
43
42
|
let(:attributes) { {} }
|
44
43
|
|
45
44
|
it 'should raise error' do
|
46
45
|
expect { subject }.to raise_error(
|
47
|
-
Anima::Error
|
48
|
-
'
|
46
|
+
Anima::Error,
|
47
|
+
'TestClass attributes missing: [:firstname, :lastname], unknown: []'
|
49
48
|
)
|
50
49
|
end
|
51
50
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -29,29 +29,24 @@ describe Anima::Attribute do
|
|
29
29
|
describe '#load' do
|
30
30
|
subject { object.load(target, attribute_hash) }
|
31
31
|
|
32
|
-
let(:target)
|
33
|
-
|
34
|
-
let(:
|
35
|
-
|
36
|
-
context 'when attribute hash contains key' do
|
37
|
-
let(:attribute_hash) { { foo: value } }
|
32
|
+
let(:target) { Object.new }
|
33
|
+
let(:value) { double('Value') }
|
34
|
+
let(:attribute_hash) { { foo: value } }
|
38
35
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
36
|
+
it 'should set value as instance variable' do
|
37
|
+
subject
|
38
|
+
expect(target.instance_variable_get(:@foo)).to be(value)
|
39
|
+
end
|
43
40
|
|
44
|
-
|
41
|
+
it_should_behave_like 'a command method'
|
42
|
+
end
|
45
43
|
|
46
|
-
|
44
|
+
describe '#instance_variable_name' do
|
45
|
+
subject { object.instance_variable_name }
|
47
46
|
|
48
|
-
|
49
|
-
let(:attribute_hash) { {} }
|
47
|
+
it { should be(:@foo) }
|
50
48
|
|
51
|
-
|
52
|
-
expect { subject }.to raise_error(Anima::Error::Missing, Anima::Error::Missing.new(target, :foo).message)
|
53
|
-
end
|
54
|
-
end
|
49
|
+
it_should_behave_like 'an idempotent method'
|
55
50
|
end
|
56
51
|
|
57
52
|
describe '#set' do
|
@@ -65,7 +60,7 @@ describe Anima::Attribute do
|
|
65
60
|
|
66
61
|
it 'should set value as instance variable' do
|
67
62
|
subject
|
68
|
-
target.instance_variable_get(:@foo).
|
63
|
+
expect(target.instance_variable_get(:@foo)).to be(value)
|
69
64
|
end
|
70
65
|
end
|
71
66
|
end
|
@@ -2,25 +2,19 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe Anima::Error
|
6
|
-
|
5
|
+
describe Anima::Error do
|
6
|
+
describe '#message' do
|
7
|
+
let(:object) { described_class.new(Anima, missing, unknown) }
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
def self.name
|
11
|
-
'Test::Error'
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
9
|
+
let(:missing) { %i[missing] }
|
10
|
+
let(:unknown) { %i[unknown] }
|
15
11
|
|
16
|
-
|
12
|
+
subject { object.message }
|
17
13
|
|
18
|
-
|
19
|
-
|
14
|
+
it 'should return the message string' do
|
15
|
+
should eql('Anima attributes missing: [:missing], unknown: [:unknown]')
|
16
|
+
end
|
20
17
|
|
21
|
-
|
22
|
-
should eql('Error attribute(s) "foo" for Object')
|
18
|
+
it_should_behave_like 'an idempotent method'
|
23
19
|
end
|
24
|
-
|
25
|
-
it_should_behave_like 'an idempotent method'
|
26
20
|
end
|
data/spec/unit/anima_spec.rb
CHANGED
@@ -89,7 +89,7 @@ describe Anima do
|
|
89
89
|
subject { target }
|
90
90
|
|
91
91
|
it 'should define attribute hash reader' do
|
92
|
-
instance.to_h.
|
92
|
+
expect(instance.to_h).to eql(foo: value)
|
93
93
|
end
|
94
94
|
|
95
95
|
its(:anima) { should be(object) }
|
@@ -109,9 +109,15 @@ describe Anima do
|
|
109
109
|
|
110
110
|
it 'should initialize target instance variables' do
|
111
111
|
subject
|
112
|
-
|
113
|
-
|
114
|
-
|
112
|
+
|
113
|
+
expect(
|
114
|
+
target
|
115
|
+
.instance_variables
|
116
|
+
.map(&:to_sym)
|
117
|
+
.to_set
|
118
|
+
).to eql(%i[@foo @bar].to_set)
|
119
|
+
expect(target.instance_variable_get(:@foo)).to be(foo)
|
120
|
+
expect(target.instance_variable_get(:@bar)).to be(bar)
|
115
121
|
end
|
116
122
|
|
117
123
|
it_should_behave_like 'a command method'
|
@@ -121,7 +127,10 @@ describe Anima do
|
|
121
127
|
let(:attribute_hash) { { foo: foo, bar: bar, baz: double('Baz') } }
|
122
128
|
|
123
129
|
it 'should raise error' do
|
124
|
-
expect { subject }.to raise_error(
|
130
|
+
expect { subject }.to raise_error(
|
131
|
+
Anima::Error,
|
132
|
+
Anima::Error.new(target.class, [], [:baz]).message
|
133
|
+
)
|
125
134
|
end
|
126
135
|
end
|
127
136
|
|
@@ -129,7 +138,9 @@ describe Anima do
|
|
129
138
|
let(:attribute_hash) { { bar: bar } }
|
130
139
|
|
131
140
|
it 'should raise error' do
|
132
|
-
expect { subject }.to raise_error(
|
141
|
+
expect { subject }.to raise_error(
|
142
|
+
Anima::Error.new(target.class, [:foo], []).message
|
143
|
+
)
|
133
144
|
end
|
134
145
|
end
|
135
146
|
end
|
@@ -162,4 +173,28 @@ describe Anima do
|
|
162
173
|
|
163
174
|
it { should eql(params) }
|
164
175
|
end
|
176
|
+
|
177
|
+
describe '#with' do
|
178
|
+
subject { object.with(attributes) }
|
179
|
+
|
180
|
+
let(:klass) do
|
181
|
+
Class.new do
|
182
|
+
include Anima.new(:foo, :bar)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
let(:object) { klass.new(foo: 1, bar: 2) }
|
187
|
+
|
188
|
+
context 'with empty attributes' do
|
189
|
+
let(:attributes) { {} }
|
190
|
+
|
191
|
+
it { should eql(object) }
|
192
|
+
end
|
193
|
+
|
194
|
+
context 'with updated attribute' do
|
195
|
+
let(:attributes) { { foo: 3 } }
|
196
|
+
|
197
|
+
it { should eql(klass.new(foo: 3, bar: 2)) }
|
198
|
+
end
|
199
|
+
end
|
165
200
|
end
|
metadata
CHANGED
@@ -1,55 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: anima
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Markus Schirp
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-09-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: adamantium
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0.
|
19
|
+
version: '0.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0.
|
26
|
+
version: '0.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: equalizer
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.0.
|
33
|
+
version: 0.0.11
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.0.
|
40
|
+
version: 0.0.11
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: abstract_type
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - ~>
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: 0.0.7
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - ~>
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 0.0.7
|
55
55
|
description:
|
@@ -59,13 +59,12 @@ extensions: []
|
|
59
59
|
extra_rdoc_files:
|
60
60
|
- README.md
|
61
61
|
files:
|
62
|
-
- .gitignore
|
63
|
-
- .rspec
|
64
|
-
- .rubocop.yml
|
65
|
-
- .travis.yml
|
62
|
+
- ".gitignore"
|
63
|
+
- ".rspec"
|
64
|
+
- ".rubocop.yml"
|
65
|
+
- ".travis.yml"
|
66
66
|
- Changelog.md
|
67
67
|
- Gemfile
|
68
|
-
- Gemfile.devtools
|
69
68
|
- Guardfile
|
70
69
|
- README.md
|
71
70
|
- Rakefile
|
@@ -81,14 +80,11 @@ files:
|
|
81
80
|
- config/yardstick.yml
|
82
81
|
- lib/anima.rb
|
83
82
|
- lib/anima/attribute.rb
|
84
|
-
- lib/anima/builder.rb
|
85
83
|
- lib/anima/error.rb
|
86
|
-
- lib/anima/update.rb
|
87
84
|
- spec/integration/simple_spec.rb
|
88
85
|
- spec/spec_helper.rb
|
89
86
|
- spec/unit/anima/attribute_spec.rb
|
90
87
|
- spec/unit/anima/error_spec.rb
|
91
|
-
- spec/unit/anima/update_spec.rb
|
92
88
|
- spec/unit/anima_spec.rb
|
93
89
|
homepage: http://github.com/mbj/anima
|
94
90
|
licenses:
|
@@ -100,17 +96,17 @@ require_paths:
|
|
100
96
|
- lib
|
101
97
|
required_ruby_version: !ruby/object:Gem::Requirement
|
102
98
|
requirements:
|
103
|
-
- -
|
99
|
+
- - ">="
|
104
100
|
- !ruby/object:Gem::Version
|
105
|
-
version:
|
101
|
+
version: 2.1.0
|
106
102
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
103
|
requirements:
|
108
|
-
- -
|
104
|
+
- - ">="
|
109
105
|
- !ruby/object:Gem::Version
|
110
106
|
version: '0'
|
111
107
|
requirements: []
|
112
108
|
rubyforge_project:
|
113
|
-
rubygems_version: 2.
|
109
|
+
rubygems_version: 2.4.5.1
|
114
110
|
signing_key:
|
115
111
|
specification_version: 4
|
116
112
|
summary: Initialize object attributes via attributes hash
|
@@ -119,6 +115,5 @@ test_files:
|
|
119
115
|
- spec/spec_helper.rb
|
120
116
|
- spec/unit/anima/attribute_spec.rb
|
121
117
|
- spec/unit/anima/error_spec.rb
|
122
|
-
- spec/unit/anima/update_spec.rb
|
123
118
|
- spec/unit/anima_spec.rb
|
124
119
|
has_rdoc:
|
data/Gemfile.devtools
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
group :development do
|
4
|
-
gem 'rake', '~> 10.1.0'
|
5
|
-
gem 'rspec', '~> 2.14.1'
|
6
|
-
gem 'yard', '~> 0.8.7'
|
7
|
-
|
8
|
-
platform :rbx do
|
9
|
-
gem 'rubysl-singleton', '~> 2.0.0'
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
group :yard do
|
14
|
-
gem 'kramdown', '~> 1.3.0'
|
15
|
-
end
|
16
|
-
|
17
|
-
group :guard do
|
18
|
-
gem 'guard', '~> 2.2.4'
|
19
|
-
gem 'guard-bundler', '~> 2.0.0'
|
20
|
-
gem 'guard-rspec', '~> 4.2.0'
|
21
|
-
gem 'guard-rubocop', '~> 1.0.0'
|
22
|
-
|
23
|
-
# file system change event handling
|
24
|
-
gem 'listen', '~> 2.4.0'
|
25
|
-
gem 'rb-fchange', '~> 0.0.6', require: false
|
26
|
-
gem 'rb-fsevent', '~> 0.9.3', require: false
|
27
|
-
gem 'rb-inotify', '~> 0.9.0', require: false
|
28
|
-
|
29
|
-
# notification handling
|
30
|
-
gem 'libnotify', '~> 0.8.0', require: false
|
31
|
-
gem 'rb-notifu', '~> 0.0.4', require: false
|
32
|
-
gem 'terminal-notifier-guard', '~> 1.5.3', require: false
|
33
|
-
end
|
34
|
-
|
35
|
-
group :metrics do
|
36
|
-
gem 'coveralls', '~> 0.7.0'
|
37
|
-
gem 'flay', '~> 2.4.0'
|
38
|
-
gem 'flog', '~> 4.2.0'
|
39
|
-
gem 'reek', '~> 1.3.2'
|
40
|
-
gem 'rubocop', '~> 0.16.0'
|
41
|
-
gem 'simplecov', '~> 0.8.2'
|
42
|
-
gem 'yardstick', '~> 0.9.7', git: 'https://github.com/dkubb/yardstick.git'
|
43
|
-
|
44
|
-
platforms :mri do
|
45
|
-
gem 'mutant', '~> 0.3.4'
|
46
|
-
end
|
47
|
-
|
48
|
-
platforms :ruby_19, :ruby_20 do
|
49
|
-
gem 'yard-spellcheck', '~> 0.1.5'
|
50
|
-
end
|
51
|
-
|
52
|
-
platform :rbx do
|
53
|
-
gem 'json', '~> 1.8.1'
|
54
|
-
gem 'racc', '~> 1.4.10'
|
55
|
-
gem 'rubysl-logger', '~> 2.0.0'
|
56
|
-
gem 'rubysl-open-uri', '~> 2.0.0'
|
57
|
-
gem 'rubysl-prettyprint', '~> 2.0.2'
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
group :benchmarks do
|
62
|
-
gem 'rbench', '~> 0.2.3'
|
63
|
-
end
|
64
|
-
|
65
|
-
platform :jruby do
|
66
|
-
group :jruby do
|
67
|
-
gem 'jruby-openssl', '~> 0.8.5'
|
68
|
-
end
|
69
|
-
end
|
data/lib/anima/builder.rb
DELETED
@@ -1,130 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
class Anima
|
4
|
-
|
5
|
-
# Builds an anima infected class
|
6
|
-
class Builder
|
7
|
-
|
8
|
-
# Static instance methods for anima infected classes
|
9
|
-
module Methods
|
10
|
-
# Initialize an anima infected object
|
11
|
-
#
|
12
|
-
# @param [#to_h] attributes
|
13
|
-
# a hash that matches anima defined attributes
|
14
|
-
#
|
15
|
-
# @return [undefined]
|
16
|
-
#
|
17
|
-
# @api public
|
18
|
-
def initialize(attributes)
|
19
|
-
self.class.anima.initialize_instance(self, attributes)
|
20
|
-
end
|
21
|
-
|
22
|
-
# Return a hash representation of an anima infected object
|
23
|
-
#
|
24
|
-
# @return [Hash]
|
25
|
-
#
|
26
|
-
# @api public
|
27
|
-
def to_h
|
28
|
-
self.class.anima.attributes_hash(self)
|
29
|
-
end
|
30
|
-
end # Methods
|
31
|
-
|
32
|
-
include Adamantium::Flat
|
33
|
-
|
34
|
-
# Infect +descendant+ with anima
|
35
|
-
#
|
36
|
-
# @param [Anima] anima
|
37
|
-
# the anima instance used for infection
|
38
|
-
#
|
39
|
-
# @param [Class, Module] descendant
|
40
|
-
# the object to infect
|
41
|
-
#
|
42
|
-
# @return [undefined]
|
43
|
-
#
|
44
|
-
# @api private
|
45
|
-
def self.call(anima, descendant)
|
46
|
-
new(anima, descendant).call
|
47
|
-
end
|
48
|
-
|
49
|
-
# Initialize a new instance
|
50
|
-
#
|
51
|
-
# @param [Anima] anima
|
52
|
-
# the anima instance used for infection
|
53
|
-
#
|
54
|
-
# @param [Class, Module] descendant
|
55
|
-
# the object to infect
|
56
|
-
#
|
57
|
-
# @return [undefined]
|
58
|
-
#
|
59
|
-
# @api private
|
60
|
-
def initialize(anima, descendant)
|
61
|
-
@anima = anima
|
62
|
-
@names = anima.attribute_names
|
63
|
-
@descendant = descendant
|
64
|
-
end
|
65
|
-
|
66
|
-
# Infect the instance with anima
|
67
|
-
#
|
68
|
-
# @return [undefined]
|
69
|
-
#
|
70
|
-
# @api private
|
71
|
-
def call
|
72
|
-
define_equalizer
|
73
|
-
define_anima_method
|
74
|
-
define_attribute_readers
|
75
|
-
descendant_exec do
|
76
|
-
include Methods
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
private
|
81
|
-
|
82
|
-
# Define equalizer
|
83
|
-
#
|
84
|
-
# @return [undefined]
|
85
|
-
#
|
86
|
-
# @api private
|
87
|
-
def define_equalizer
|
88
|
-
descendant_exec(@names) do |names|
|
89
|
-
include Equalizer.new(*names)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
# Define anima method
|
94
|
-
#
|
95
|
-
# @return [undefined]
|
96
|
-
#
|
97
|
-
# @api private
|
98
|
-
def define_anima_method
|
99
|
-
descendant_exec(@anima) do |anima|
|
100
|
-
define_singleton_method(:anima) { anima }
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
# Define attribute readers
|
105
|
-
#
|
106
|
-
# @return [undefined]
|
107
|
-
#
|
108
|
-
# @api private
|
109
|
-
def define_attribute_readers
|
110
|
-
descendant_exec(@names) do |names|
|
111
|
-
attr_reader(*names)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
# Deduplicate instance_exec inside descendant's scope
|
116
|
-
#
|
117
|
-
# @param [*] *args
|
118
|
-
# arguments to pass to instance_exec
|
119
|
-
#
|
120
|
-
# @param [Proc] &block
|
121
|
-
# the block to eval
|
122
|
-
#
|
123
|
-
# @return [undefined]
|
124
|
-
#
|
125
|
-
# @api private
|
126
|
-
def descendant_exec(*args, &block)
|
127
|
-
@descendant.instance_exec(*args, &block)
|
128
|
-
end
|
129
|
-
end # Builder
|
130
|
-
end # Anima
|
data/lib/anima/update.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
class Anima
|
4
|
-
# Module for mixin in update functionallity to anima infected clases
|
5
|
-
module Update
|
6
|
-
|
7
|
-
# Return updated instance
|
8
|
-
#
|
9
|
-
# @example
|
10
|
-
# klass = Class.new do
|
11
|
-
# include Anima.new(:foo, :bar), Anima::Update
|
12
|
-
# end
|
13
|
-
#
|
14
|
-
# foo = klass.new(:foo => 1, :bar => 2)
|
15
|
-
# updated = foo.update(:foo => 3)
|
16
|
-
# updated.foo # => 3
|
17
|
-
# updated.bar # => 2
|
18
|
-
#
|
19
|
-
# @param [Hash] attributes
|
20
|
-
#
|
21
|
-
# @return [Anima]
|
22
|
-
#
|
23
|
-
# @api private
|
24
|
-
#
|
25
|
-
def update(attributes)
|
26
|
-
self.class.new(to_h.update(attributes))
|
27
|
-
end
|
28
|
-
|
29
|
-
end # Update
|
30
|
-
end # Anima
|
@@ -1,27 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
require 'spec_helper'
|
4
|
-
|
5
|
-
describe Anima::Update, '#update' do
|
6
|
-
subject { object.update(attributes) }
|
7
|
-
|
8
|
-
let(:object) { class_under_test.new(foo: 1, bar: 2) }
|
9
|
-
|
10
|
-
let(:class_under_test) do
|
11
|
-
Class.new do
|
12
|
-
include Anima.new(:foo, :bar), Anima::Update
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
context 'with empty attributes' do
|
17
|
-
let(:attributes) { {} }
|
18
|
-
|
19
|
-
it { should eql(object) }
|
20
|
-
end
|
21
|
-
|
22
|
-
context 'with updated attribute' do
|
23
|
-
let(:attributes) { { foo: 3 } }
|
24
|
-
|
25
|
-
it { should eql(class_under_test.new(foo: 3, bar: 2)) }
|
26
|
-
end
|
27
|
-
end
|