anima 0.0.7 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +1 -2
- data/Gemfile +1 -1
- data/README.md +57 -4
- data/anima.gemspec +2 -1
- data/config/flay.yml +1 -1
- data/config/reek.yml +1 -1
- data/config/rubocop.yml +85 -0
- data/lib/anima.rb +42 -2
- data/lib/anima/attribute.rb +15 -17
- data/lib/anima/update.rb +3 -3
- data/spec/integration/simple_spec.rb +7 -7
- data/spec/unit/anima/attribute_spec.rb +98 -0
- data/spec/unit/anima/{error/message_spec.rb → error_spec.rb} +1 -1
- data/spec/unit/anima/{update/update_spec.rb → update_spec.rb} +4 -4
- data/spec/unit/anima_spec.rb +134 -0
- metadata +13 -25
- data/spec/unit/anima/attribute/define_reader_spec.rb +0 -24
- data/spec/unit/anima/attribute/get_spec.rb +0 -25
- data/spec/unit/anima/attribute/instance_variable_name_spec.rb +0 -9
- data/spec/unit/anima/attribute/load_spec.rb +0 -31
- data/spec/unit/anima/attribute/set_spec.rb +0 -18
- data/spec/unit/anima/attributes_hash_spec.rb +0 -13
- data/spec/unit/anima/attributes_spec.rb +0 -10
- data/spec/unit/anima/included_spec.rb +0 -36
- data/spec/unit/anima/initialize_instance_spec.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8829390b1d9de51fddff518775263b3d349298bc
|
4
|
+
data.tar.gz: b7cfafb8c2c03195da23c1cfe3a26be3d20c93fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9ef1d565f8abe13a9914af0439b2bae68a3350819b240a1dbedf565d50a5c1639696282b676db17ede25d8d82a82aa2355fe7ad2584fbcdd502ee0cddc602769
|
7
|
+
data.tar.gz: cef667e63a0f638bd8ed31474fce8dde15df03922b1f3d069a4829b328a795e5d906267e09ca1c999cc675084beb77deb556412d784c485d865820cb141e435a
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -5,21 +5,74 @@ anima
|
|
5
5
|
[](https://gemnasium.com/mbj/anima)
|
6
6
|
[](https://codeclimate.com/github/mbj/anima)
|
7
7
|
|
8
|
-
Simple library to declare read only attributes on objects that are
|
8
|
+
Simple library to declare read only attributes on value-objects that are initialized via attributes hash.
|
9
9
|
|
10
10
|
Installation
|
11
11
|
------------
|
12
12
|
|
13
|
-
|
13
|
+
Install the gem `anima` via your preferred method.
|
14
14
|
|
15
15
|
Examples
|
16
16
|
--------
|
17
17
|
|
18
|
-
|
18
|
+
```
|
19
|
+
# Definition
|
20
|
+
class Person
|
21
|
+
include Anima.new(:salutation, :firstname, :lastname)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Every day operation
|
25
|
+
a = Person.new(
|
26
|
+
:salutation => 'Mr',
|
27
|
+
:firstname => 'Markus',
|
28
|
+
:lastname => 'Schirp'
|
29
|
+
)
|
30
|
+
|
31
|
+
a.salutation # => "Mr"
|
32
|
+
a.firstname # => "Markus"
|
33
|
+
a.lastname # => "Schirp"
|
34
|
+
a.frozen? # => true
|
35
|
+
|
36
|
+
b = Person.new(
|
37
|
+
:salutation => 'Mr',
|
38
|
+
:firstname => 'John',
|
39
|
+
:lastname => 'Doe'
|
40
|
+
)
|
41
|
+
|
42
|
+
a = Person.new(
|
43
|
+
:salutation => 'Mr',
|
44
|
+
:firstname => 'Markus',
|
45
|
+
:lastname => 'Schirp'
|
46
|
+
)
|
47
|
+
|
48
|
+
a == b # => false
|
49
|
+
a.eql?(b) # => false
|
50
|
+
a.equal?(b) # => false
|
51
|
+
|
52
|
+
a == c # => true
|
53
|
+
a.eql?(c) # => true
|
54
|
+
a.equal?(c) # => false
|
55
|
+
|
56
|
+
# Functional updates
|
57
|
+
class Person
|
58
|
+
include Anima::Update
|
59
|
+
end
|
60
|
+
|
61
|
+
d = b.update(
|
62
|
+
:salutation => 'Mrs',
|
63
|
+
:firstname => 'Sue',
|
64
|
+
)
|
65
|
+
|
66
|
+
# It returns copies, no inplace modification
|
67
|
+
d.equal?(b) # => false
|
68
|
+
|
69
|
+
```
|
19
70
|
|
20
71
|
Credits
|
21
72
|
-------
|
22
73
|
|
74
|
+
* Markus Schirp <mbj@schirp-dso.com>
|
75
|
+
|
23
76
|
Contributing
|
24
77
|
-------------
|
25
78
|
|
@@ -34,7 +87,7 @@ Contributing
|
|
34
87
|
License
|
35
88
|
-------
|
36
89
|
|
37
|
-
Copyright (c)
|
90
|
+
Copyright (c) 2013 Markus Schirp
|
38
91
|
|
39
92
|
Permission is hereby granted, free of charge, to any person obtaining
|
40
93
|
a copy of this software and associated documentation files (the
|
data/anima.gemspec
CHANGED
@@ -2,12 +2,13 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'anima'
|
5
|
-
s.version = '0.0
|
5
|
+
s.version = '0.1.0'
|
6
6
|
|
7
7
|
s.authors = ['Markus Schirp']
|
8
8
|
s.email = 'mbj@schirp-dso.com'
|
9
9
|
s.summary = 'Attributes for Plain Old Ruby Objects Experiment'
|
10
10
|
s.homepage = 'http://github.com/mbj/anima'
|
11
|
+
s.license = 'MIT'
|
11
12
|
|
12
13
|
s.files = `git ls-files`.split("\n")
|
13
14
|
s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
|
data/config/flay.yml
CHANGED
data/config/reek.yml
CHANGED
data/config/rubocop.yml
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
AllCops:
|
2
|
+
Includes:
|
3
|
+
- '../**/*.rake'
|
4
|
+
- 'Gemfile'
|
5
|
+
- 'Gemfile.devtools'
|
6
|
+
- 'mutant.gemspec'
|
7
|
+
Excludes:
|
8
|
+
- '**/vendor/**'
|
9
|
+
- '**/benchmarks/**'
|
10
|
+
|
11
|
+
# Avoid parameter lists longer than five parameters.
|
12
|
+
ParameterLists:
|
13
|
+
Max: 3
|
14
|
+
CountKeywordArgs: true
|
15
|
+
|
16
|
+
# Avoid more than `Max` levels of nesting.
|
17
|
+
BlockNesting:
|
18
|
+
Max: 3
|
19
|
+
|
20
|
+
# Align with the style guide.
|
21
|
+
CollectionMethods:
|
22
|
+
PreferredMethods:
|
23
|
+
collect: 'map'
|
24
|
+
inject: 'reduce'
|
25
|
+
find: 'detect'
|
26
|
+
find_all: 'select'
|
27
|
+
|
28
|
+
# Do not force public/protected/private keyword to be indented at the same
|
29
|
+
# level as the def keyword. My personal preference is to outdent these keywords
|
30
|
+
# because I think when scanning code it makes it easier to identify the
|
31
|
+
# sections of code and visually separate them. When the keyword is at the same
|
32
|
+
# level I think it sort of blends in with the def keywords and makes it harder
|
33
|
+
# to scan the code and see where the sections are.
|
34
|
+
AccessControl:
|
35
|
+
Enabled: false
|
36
|
+
|
37
|
+
MethodLength:
|
38
|
+
CountComments: false
|
39
|
+
Max: 17 # TODO: Bring down to 10
|
40
|
+
|
41
|
+
RegexpLiteral: # I do not agree %r(\A) is more readable than /\A/
|
42
|
+
Enabled: false
|
43
|
+
|
44
|
+
Eval:
|
45
|
+
Enabled: false # Mutant must use Kernel#eval to inject mutated source
|
46
|
+
|
47
|
+
# Limit line length
|
48
|
+
LineLength:
|
49
|
+
Max: 124 # TODO: lower to 79
|
50
|
+
|
51
|
+
# Disable documentation checking until a class needs to be documented once
|
52
|
+
Documentation:
|
53
|
+
Enabled: false
|
54
|
+
|
55
|
+
# Do not favor modifier if/unless usage when you have a single-line body
|
56
|
+
IfUnlessModifier:
|
57
|
+
Enabled: false
|
58
|
+
|
59
|
+
# Mutant needs to define methods like def bar; end in specs
|
60
|
+
Semicolon:
|
61
|
+
Enabled: false
|
62
|
+
|
63
|
+
# Mutant needs to define multiple methods on same line in specs
|
64
|
+
EmptyLineBetweenDefs:
|
65
|
+
Enabled: false
|
66
|
+
|
67
|
+
# Mutant needs to define singleton methods like Foo.bar in specs
|
68
|
+
ClassMethods:
|
69
|
+
Enabled: false
|
70
|
+
|
71
|
+
# Allow case equality operator (in limited use within the specs)
|
72
|
+
CaseEquality:
|
73
|
+
Enabled: false
|
74
|
+
|
75
|
+
# Constants do not always have to use SCREAMING_SNAKE_CASE
|
76
|
+
ConstantName:
|
77
|
+
Enabled: false
|
78
|
+
|
79
|
+
# Not all trivial readers/writers can be defined with attr_* methods
|
80
|
+
TrivialAccessors:
|
81
|
+
Enabled: false
|
82
|
+
|
83
|
+
# And also have a differend opinion here
|
84
|
+
AndOr:
|
85
|
+
Enabled: false
|
data/lib/anima.rb
CHANGED
@@ -5,7 +5,7 @@ require 'abstract_type'
|
|
5
5
|
|
6
6
|
# Main library namespace and mixin
|
7
7
|
class Anima < Module
|
8
|
-
include Adamantium::Flat
|
8
|
+
include Adamantium::Flat, Equalizer.new(:attributes)
|
9
9
|
|
10
10
|
# Return names
|
11
11
|
#
|
@@ -22,7 +22,35 @@ class Anima < Module
|
|
22
22
|
# @api private
|
23
23
|
#
|
24
24
|
def initialize(*names)
|
25
|
-
@attributes = names.map { |name| Attribute.new(name) }.freeze
|
25
|
+
@attributes = names.uniq.map { |name| Attribute.new(name) }.freeze
|
26
|
+
end
|
27
|
+
|
28
|
+
# Return new anima with attributes removed
|
29
|
+
#
|
30
|
+
# @return [Anima]
|
31
|
+
#
|
32
|
+
# @example
|
33
|
+
# anima = Anima.new(:foo)
|
34
|
+
# anima.add(:foo) # equals Anima.new(:foo, :bar)
|
35
|
+
#
|
36
|
+
# @api public
|
37
|
+
#
|
38
|
+
def remove(*names)
|
39
|
+
new(attribute_names - names)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Return new anima with attributes added
|
43
|
+
#
|
44
|
+
# @return [Anima]
|
45
|
+
#
|
46
|
+
# @example
|
47
|
+
# anima = Anima.new(:foo, :bar)
|
48
|
+
# anima.remove(:bar) # equals Anima.new(:foo)
|
49
|
+
#
|
50
|
+
# @api private
|
51
|
+
#
|
52
|
+
def add(*names)
|
53
|
+
new(attribute_names + names)
|
26
54
|
end
|
27
55
|
|
28
56
|
# Return attributes hash for instance
|
@@ -92,6 +120,18 @@ private
|
|
92
120
|
define_equalizer(scope)
|
93
121
|
end
|
94
122
|
|
123
|
+
# Return new instance
|
124
|
+
#
|
125
|
+
# @param [Enumerable<Symbol>] attributes
|
126
|
+
#
|
127
|
+
# @return [Anima]
|
128
|
+
#
|
129
|
+
# @api private
|
130
|
+
#
|
131
|
+
def new(attributes)
|
132
|
+
self.class.new(*attributes)
|
133
|
+
end
|
134
|
+
|
95
135
|
# Define anima method on scope
|
96
136
|
#
|
97
137
|
# @param [Class, Module] scope
|
data/lib/anima/attribute.rb
CHANGED
@@ -4,6 +4,16 @@ class Anima
|
|
4
4
|
class Attribute
|
5
5
|
include Adamantium::Flat, Equalizer.new(:name)
|
6
6
|
|
7
|
+
# Initialize attribute
|
8
|
+
#
|
9
|
+
# @param [Symbol] name
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
#
|
13
|
+
def initialize(name)
|
14
|
+
@name = name
|
15
|
+
end
|
16
|
+
|
7
17
|
# Return attribute name
|
8
18
|
#
|
9
19
|
# @return [Symbol]
|
@@ -11,7 +21,7 @@ class Anima
|
|
11
21
|
# @api private
|
12
22
|
#
|
13
23
|
attr_reader :name
|
14
|
-
|
24
|
+
|
15
25
|
# Load attribute
|
16
26
|
#
|
17
27
|
# @param [Object] object
|
@@ -24,7 +34,7 @@ class Anima
|
|
24
34
|
def load(object, attributes)
|
25
35
|
attribute_name = name
|
26
36
|
|
27
|
-
value = attributes.fetch(attribute_name) do
|
37
|
+
value = attributes.fetch(attribute_name) do
|
28
38
|
raise Error::Missing.new(object.class, attribute_name)
|
29
39
|
end
|
30
40
|
|
@@ -35,7 +45,7 @@ class Anima
|
|
35
45
|
#
|
36
46
|
# @param [Object] object
|
37
47
|
#
|
38
|
-
# @return [Object]
|
48
|
+
# @return [Object]
|
39
49
|
#
|
40
50
|
# @api private
|
41
51
|
#
|
@@ -83,17 +93,5 @@ class Anima
|
|
83
93
|
self
|
84
94
|
end
|
85
95
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
# Initialize attribute
|
90
|
-
#
|
91
|
-
# @param [Symbol] name
|
92
|
-
#
|
93
|
-
# @api private
|
94
|
-
#
|
95
|
-
def initialize(name)
|
96
|
-
@name = name
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
96
|
+
end # Attribute
|
97
|
+
end # Anima
|
data/lib/anima/update.rb
CHANGED
@@ -5,14 +5,14 @@ class Anima
|
|
5
5
|
# Return updated instance
|
6
6
|
#
|
7
7
|
# @example
|
8
|
-
# klass = Class.new do
|
8
|
+
# klass = Class.new do
|
9
9
|
# include Anima.new(:foo, :bar), Anima::Update
|
10
10
|
# end
|
11
11
|
#
|
12
12
|
# foo = klass.new(:foo => 1, :bar => 2)
|
13
13
|
# updated = foo.update(:foo => 3)
|
14
|
-
# updated.foo # => 3
|
15
|
-
# updated.bar # => 2
|
14
|
+
# updated.foo # => 3
|
15
|
+
# updated.bar # => 2
|
16
16
|
#
|
17
17
|
# @param [Hash] attributes
|
18
18
|
#
|
@@ -16,8 +16,8 @@ describe Anima, 'simple integration' do
|
|
16
16
|
context 'when instanciated with all attributes' do
|
17
17
|
let(:attributes) do
|
18
18
|
{
|
19
|
-
:
|
20
|
-
:
|
19
|
+
firstname: 'Markus',
|
20
|
+
lastname: 'Schirp'
|
21
21
|
}
|
22
22
|
end
|
23
23
|
|
@@ -26,17 +26,17 @@ describe Anima, 'simple integration' do
|
|
26
26
|
end
|
27
27
|
|
28
28
|
context 'with instanciated with extra attributes' do
|
29
|
-
let(:attributes) do
|
29
|
+
let(:attributes) do
|
30
30
|
{
|
31
|
-
:
|
32
|
-
:
|
33
|
-
:
|
31
|
+
firstname: 'Markus',
|
32
|
+
lastname: 'Schirp',
|
33
|
+
extra: 'Foo'
|
34
34
|
}
|
35
35
|
end
|
36
36
|
|
37
37
|
it 'should raise error' do
|
38
38
|
expect { subject }.to raise_error(
|
39
|
-
Anima::Error::Unknown,
|
39
|
+
Anima::Error::Unknown,
|
40
40
|
'Unknown attribute(s) [:extra] for TestClass'
|
41
41
|
)
|
42
42
|
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Anima::Attribute do
|
4
|
+
let(:object) { described_class.new(:foo) }
|
5
|
+
|
6
|
+
describe '#define_reader' do
|
7
|
+
subject { object.define_reader(target_class) }
|
8
|
+
|
9
|
+
let(:target_class) do
|
10
|
+
Class.new do
|
11
|
+
def initialize(foo)
|
12
|
+
@foo = foo
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:value) { double('Value') }
|
18
|
+
|
19
|
+
it 'should create a reader' do
|
20
|
+
instance = target_class.new(value)
|
21
|
+
-> { subject }.should change { instance.respond_to?(:foo) }.from(false).to(true)
|
22
|
+
end
|
23
|
+
|
24
|
+
it_should_behave_like 'a command method'
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#get' do
|
28
|
+
subject { object.get(target) }
|
29
|
+
|
30
|
+
let(:target_class) do
|
31
|
+
Class.new do
|
32
|
+
attr_reader :foo
|
33
|
+
|
34
|
+
def initialize(foo)
|
35
|
+
@foo = foo
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
let(:target) { target_class.new(value) }
|
41
|
+
let(:value) { double('Value') }
|
42
|
+
|
43
|
+
it 'should return value' do
|
44
|
+
should be(value)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#instance_variable_name' do
|
49
|
+
subject { Anima::Attribute.new(:foo).instance_variable_name }
|
50
|
+
|
51
|
+
it { should be(:@foo) }
|
52
|
+
|
53
|
+
it_should_behave_like 'an idempotent method'
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#load' do
|
57
|
+
subject { object.load(target, attribute_hash) }
|
58
|
+
|
59
|
+
let(:target) { Object.new }
|
60
|
+
|
61
|
+
let(:value) { double('Value') }
|
62
|
+
|
63
|
+
context 'when attribute hash contains key' do
|
64
|
+
let(:attribute_hash) { { foo: value } }
|
65
|
+
|
66
|
+
it 'should set value as instance variable' do
|
67
|
+
subject
|
68
|
+
target.instance_variable_get(:@foo).should be(value)
|
69
|
+
end
|
70
|
+
|
71
|
+
it_should_behave_like 'a command method'
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'when attribute hash does not contain key' do
|
76
|
+
let(:attribute_hash) { {} }
|
77
|
+
|
78
|
+
it 'should raise error' do
|
79
|
+
expect { subject }.to raise_error(Anima::Error::Missing, Anima::Error::Missing.new(target.class, :foo).message)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe '#set' do
|
85
|
+
subject { object.set(target, value) }
|
86
|
+
|
87
|
+
let(:target) { Object.new }
|
88
|
+
|
89
|
+
let(:value) { double('Value') }
|
90
|
+
|
91
|
+
it_should_behave_like 'a command method'
|
92
|
+
|
93
|
+
it 'should set value as instance variable' do
|
94
|
+
subject
|
95
|
+
target.instance_variable_get(:@foo).should be(value)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -3,10 +3,10 @@ require 'spec_helper'
|
|
3
3
|
describe Anima::Update, '#update' do
|
4
4
|
subject { object.update(attributes) }
|
5
5
|
|
6
|
-
let(:object) { class_under_test.new(:
|
6
|
+
let(:object) { class_under_test.new(foo: 1, bar: 2) }
|
7
7
|
|
8
8
|
let(:class_under_test) do
|
9
|
-
Class.new do
|
9
|
+
Class.new do
|
10
10
|
include Anima.new(:foo, :bar), Anima::Update
|
11
11
|
end
|
12
12
|
end
|
@@ -18,8 +18,8 @@ describe Anima::Update, '#update' do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
context 'with updated attribute' do
|
21
|
-
let(:attributes) { {:
|
21
|
+
let(:attributes) { { foo: 3 } }
|
22
22
|
|
23
|
-
it { should eql(class_under_test.new(:
|
23
|
+
it { should eql(class_under_test.new(foo: 3, bar: 2)) }
|
24
24
|
end
|
25
25
|
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Anima do
|
4
|
+
|
5
|
+
let(:object) { described_class.new(:foo) }
|
6
|
+
|
7
|
+
describe '#attributes_hash' do
|
8
|
+
|
9
|
+
let(:value) { double('Value') }
|
10
|
+
|
11
|
+
let(:instance) { double(foo: value) }
|
12
|
+
|
13
|
+
subject { object.attributes_hash(instance) }
|
14
|
+
|
15
|
+
it { should eql(foo: value) }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#remove' do
|
19
|
+
let(:object) { described_class.new(:foo, :bar) }
|
20
|
+
|
21
|
+
context 'with single attribute' do
|
22
|
+
subject { object.remove(:bar) }
|
23
|
+
it { should eql(described_class.new(:foo)) }
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'with multiple attributes' do
|
27
|
+
subject { object.remove(:foo, :bar) }
|
28
|
+
it { should eql(described_class.new) }
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'with inexisting attribute' do
|
32
|
+
subject { object.remove(:baz) }
|
33
|
+
|
34
|
+
it { should eql(object) }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#add' do
|
39
|
+
context 'with single attribute' do
|
40
|
+
subject { object.add(:bar) }
|
41
|
+
it { should eql(described_class.new(:foo, :bar)) }
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'with multiple attributes' do
|
45
|
+
subject { object.add(:bar, :baz) }
|
46
|
+
it { should eql(described_class.new(:foo, :bar, :baz)) }
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'with duplicate attribute ' do
|
50
|
+
subject { object.add(:foo) }
|
51
|
+
it { should eql(object) }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe '#attributes' do
|
56
|
+
subject { object.attributes }
|
57
|
+
|
58
|
+
it { should eql([Anima::Attribute.new(:foo)]) }
|
59
|
+
it { should be_frozen }
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#included' do
|
63
|
+
let(:target) do
|
64
|
+
object = self.object
|
65
|
+
Class.new do
|
66
|
+
include object
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
let(:value) { double('Value') }
|
71
|
+
|
72
|
+
let(:instance) { target.new(foo: value) }
|
73
|
+
let(:instance_b) { target.new(foo: value) }
|
74
|
+
let(:instance_c) { target.new(foo: double('Bar')) }
|
75
|
+
|
76
|
+
context 'on instance' do
|
77
|
+
subject { instance }
|
78
|
+
|
79
|
+
its(:foo) { should be(value) }
|
80
|
+
|
81
|
+
it { should eql(instance_b) }
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'on singleton' do
|
85
|
+
subject { target }
|
86
|
+
|
87
|
+
it 'should define attribute hash reader' do
|
88
|
+
target.attributes_hash(instance).should eql(foo: value)
|
89
|
+
end
|
90
|
+
|
91
|
+
its(:anima) { should be(object) }
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe '#initialize_instance' do
|
96
|
+
let(:object) { Anima.new(:foo, :bar) }
|
97
|
+
|
98
|
+
let(:target) { Object.new }
|
99
|
+
|
100
|
+
let(:foo) { double('Foo') }
|
101
|
+
let(:bar) { double('Bar') }
|
102
|
+
|
103
|
+
subject { object.initialize_instance(target, attribute_hash) }
|
104
|
+
|
105
|
+
context 'when all keys are present in attribute hash' do
|
106
|
+
let(:attribute_hash) { { foo: foo, bar: bar } }
|
107
|
+
|
108
|
+
it 'should initialize target instance variables' do
|
109
|
+
subject
|
110
|
+
target.instance_variables.map(&:to_sym).to_set.should eql([:@foo, :@bar].to_set)
|
111
|
+
target.instance_variable_get(:@foo).should be(foo)
|
112
|
+
target.instance_variable_get(:@bar).should be(bar)
|
113
|
+
end
|
114
|
+
|
115
|
+
it_should_behave_like 'a command method'
|
116
|
+
end
|
117
|
+
|
118
|
+
context 'when extra key is missing in attribute hash' do
|
119
|
+
let(:attribute_hash) { { foo: foo, bar: bar, baz: double('Baz') } }
|
120
|
+
|
121
|
+
it 'should raise error' do
|
122
|
+
expect { subject }.to raise_error(Anima::Error::Unknown, Anima::Error::Unknown.new(target.class, [:baz]).message)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context 'when a key is missing in attribute hash' do
|
127
|
+
let(:attribute_hash) { { bar: bar } }
|
128
|
+
|
129
|
+
it 'should raise error' do
|
130
|
+
expect { subject }.to raise_error(Anima::Error::Missing, Anima::Error::Missing.new(target.class, :foo).message)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: anima
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.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: 2013-08
|
11
|
+
date: 2013-09-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: adamantium
|
@@ -75,6 +75,7 @@ files:
|
|
75
75
|
- config/mutant.yml
|
76
76
|
- config/reek.yml
|
77
77
|
- config/roodi.yml
|
78
|
+
- config/rubocop.yml
|
78
79
|
- config/yardstick.yml
|
79
80
|
- lib/anima.rb
|
80
81
|
- lib/anima/attribute.rb
|
@@ -82,19 +83,13 @@ files:
|
|
82
83
|
- lib/anima/update.rb
|
83
84
|
- spec/integration/simple_spec.rb
|
84
85
|
- spec/spec_helper.rb
|
85
|
-
- spec/unit/anima/
|
86
|
-
- spec/unit/anima/
|
87
|
-
- spec/unit/anima/
|
88
|
-
- spec/unit/
|
89
|
-
- spec/unit/anima/attribute/set_spec.rb
|
90
|
-
- spec/unit/anima/attributes_hash_spec.rb
|
91
|
-
- spec/unit/anima/attributes_spec.rb
|
92
|
-
- spec/unit/anima/error/message_spec.rb
|
93
|
-
- spec/unit/anima/included_spec.rb
|
94
|
-
- spec/unit/anima/initialize_instance_spec.rb
|
95
|
-
- spec/unit/anima/update/update_spec.rb
|
86
|
+
- spec/unit/anima/attribute_spec.rb
|
87
|
+
- spec/unit/anima/error_spec.rb
|
88
|
+
- spec/unit/anima/update_spec.rb
|
89
|
+
- spec/unit/anima_spec.rb
|
96
90
|
homepage: http://github.com/mbj/anima
|
97
|
-
licenses:
|
91
|
+
licenses:
|
92
|
+
- MIT
|
98
93
|
metadata: {}
|
99
94
|
post_install_message:
|
100
95
|
rdoc_options: []
|
@@ -119,15 +114,8 @@ summary: Attributes for Plain Old Ruby Objects Experiment
|
|
119
114
|
test_files:
|
120
115
|
- spec/integration/simple_spec.rb
|
121
116
|
- spec/spec_helper.rb
|
122
|
-
- spec/unit/anima/
|
123
|
-
- spec/unit/anima/
|
124
|
-
- spec/unit/anima/
|
125
|
-
- spec/unit/
|
126
|
-
- spec/unit/anima/attribute/set_spec.rb
|
127
|
-
- spec/unit/anima/attributes_hash_spec.rb
|
128
|
-
- spec/unit/anima/attributes_spec.rb
|
129
|
-
- spec/unit/anima/error/message_spec.rb
|
130
|
-
- spec/unit/anima/included_spec.rb
|
131
|
-
- spec/unit/anima/initialize_instance_spec.rb
|
132
|
-
- spec/unit/anima/update/update_spec.rb
|
117
|
+
- spec/unit/anima/attribute_spec.rb
|
118
|
+
- spec/unit/anima/error_spec.rb
|
119
|
+
- spec/unit/anima/update_spec.rb
|
120
|
+
- spec/unit/anima_spec.rb
|
133
121
|
has_rdoc:
|
@@ -1,24 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Anima::Attribute, '#define_reader' do
|
4
|
-
let(:object) { described_class.new(:foo) }
|
5
|
-
|
6
|
-
subject { object.define_reader(target_class) }
|
7
|
-
|
8
|
-
let(:target_class) do
|
9
|
-
Class.new do
|
10
|
-
def initialize(foo)
|
11
|
-
@foo = foo
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
let(:value) { double('Value') }
|
17
|
-
|
18
|
-
it 'should create a reader' do
|
19
|
-
instance = target_class.new(value)
|
20
|
-
lambda { subject }.should change { instance.respond_to?(:foo) }.from(false).to(true)
|
21
|
-
end
|
22
|
-
|
23
|
-
it_should_behave_like 'a command method'
|
24
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Anima::Attribute, '#get' do
|
4
|
-
let(:object) { described_class.new(:foo) }
|
5
|
-
|
6
|
-
subject { object.get(target) }
|
7
|
-
|
8
|
-
let(:target_class) do
|
9
|
-
Class.new do
|
10
|
-
attr_reader :foo
|
11
|
-
|
12
|
-
def initialize(foo)
|
13
|
-
@foo = foo
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
let(:target) { target_class.new(value) }
|
19
|
-
|
20
|
-
let(:value) { double('Value') }
|
21
|
-
|
22
|
-
it 'should return value' do
|
23
|
-
should be(value)
|
24
|
-
end
|
25
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Anima::Attribute, '#load' do
|
4
|
-
let(:object) { described_class.new(:foo) }
|
5
|
-
|
6
|
-
subject { object.load(target, attribute_hash) }
|
7
|
-
|
8
|
-
let(:target) { Object.new }
|
9
|
-
|
10
|
-
let(:value) { double('Value') }
|
11
|
-
|
12
|
-
context 'when attribute hash contains key' do
|
13
|
-
let(:attribute_hash) { { :foo => value } }
|
14
|
-
|
15
|
-
it 'should set value as instance variable' do
|
16
|
-
subject
|
17
|
-
target.instance_variable_get(:@foo).should be(value)
|
18
|
-
end
|
19
|
-
|
20
|
-
it_should_behave_like 'a command method'
|
21
|
-
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'when attribute hash does not contain key' do
|
25
|
-
let(:attribute_hash) { {} }
|
26
|
-
|
27
|
-
it 'should raise error' do
|
28
|
-
expect { subject }.to raise_error(Anima::Error::Missing, Anima::Error::Missing.new(target.class, :foo).message)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Anima::Attribute, '#set' do
|
4
|
-
let(:object) { described_class.new(:foo) }
|
5
|
-
|
6
|
-
subject { object.set(target, value) }
|
7
|
-
|
8
|
-
let(:target) { Object.new }
|
9
|
-
|
10
|
-
let(:value) { double('Value') }
|
11
|
-
|
12
|
-
it_should_behave_like 'a command method'
|
13
|
-
|
14
|
-
it 'should set value as instance variable' do
|
15
|
-
subject
|
16
|
-
target.instance_variable_get(:@foo).should be(value)
|
17
|
-
end
|
18
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Anima, '#attributes_hash' do
|
4
|
-
let(:object) { described_class.new(:foo) }
|
5
|
-
|
6
|
-
let(:value) { double('Value') }
|
7
|
-
|
8
|
-
let(:instance) { double(:foo => value) }
|
9
|
-
|
10
|
-
subject { object.attributes_hash(instance) }
|
11
|
-
|
12
|
-
it { should eql(:foo => value) }
|
13
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Anima, '#included' do
|
4
|
-
let(:object) { described_class.new(:foo) }
|
5
|
-
|
6
|
-
let(:target) do
|
7
|
-
object = self.object
|
8
|
-
Class.new do
|
9
|
-
include object
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
let(:value) { double('Value') }
|
14
|
-
|
15
|
-
let(:instance) { target.new(:foo => value) }
|
16
|
-
let(:instance_b) { target.new(:foo => value) }
|
17
|
-
let(:instance_c) { target.new(:foo => double('Bar')) }
|
18
|
-
|
19
|
-
context 'on instance' do
|
20
|
-
subject { instance }
|
21
|
-
|
22
|
-
its(:foo) { should be(value) }
|
23
|
-
|
24
|
-
it { should eql(instance_b) }
|
25
|
-
end
|
26
|
-
|
27
|
-
context 'on singleton' do
|
28
|
-
subject { target }
|
29
|
-
|
30
|
-
it 'should define attribute hash reader' do
|
31
|
-
target.attributes_hash(instance).should eql(:foo => value)
|
32
|
-
end
|
33
|
-
|
34
|
-
its(:anima) { should be(object) }
|
35
|
-
end
|
36
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Anima, '#initialize_instance' do
|
4
|
-
let(:object) { Anima.new(:foo, :bar) }
|
5
|
-
|
6
|
-
let(:target) { Object.new }
|
7
|
-
|
8
|
-
let(:foo) { double('Foo') }
|
9
|
-
let(:bar) { double('Bar') }
|
10
|
-
|
11
|
-
subject { object.initialize_instance(target, attribute_hash) }
|
12
|
-
|
13
|
-
context 'when all keys are present in attribute hash' do
|
14
|
-
let(:attribute_hash) { { :foo => foo, :bar => bar } }
|
15
|
-
|
16
|
-
it 'should initialize target instance variables' do
|
17
|
-
subject
|
18
|
-
target.instance_variables.map(&:to_sym).to_set.should eql([:@foo, :@bar].to_set)
|
19
|
-
target.instance_variable_get(:@foo).should be(foo)
|
20
|
-
target.instance_variable_get(:@bar).should be(bar)
|
21
|
-
end
|
22
|
-
|
23
|
-
it_should_behave_like 'a command method'
|
24
|
-
end
|
25
|
-
|
26
|
-
context 'when extra key is missing in attribute hash' do
|
27
|
-
let(:attribute_hash) { { :foo => foo, :bar => bar, :baz => double('Baz') } }
|
28
|
-
|
29
|
-
it 'should raise error' do
|
30
|
-
expect { subject }.to raise_error(Anima::Error::Unknown, Anima::Error::Unknown.new(target.class, [:baz]).message)
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
context 'when a key is missing in attribute hash' do
|
35
|
-
let(:attribute_hash) { { :bar => bar } }
|
36
|
-
|
37
|
-
it 'should raise error' do
|
38
|
-
expect { subject }.to raise_error(Anima::Error::Missing, Anima::Error::Missing.new(target.class, :foo).message)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|