virtus-mapper 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3d6d28f150fb62eacfa306509f4dcdd028c11aaf
4
- data.tar.gz: 0be0b2f44a38c3d9e300fa5be1c1f43864723418
3
+ metadata.gz: 1668de6a4647f8f728f267188e4d4709a6f539bb
4
+ data.tar.gz: 68dc9ee28a36a7d481158b8a3d66c0a84a5e75fe
5
5
  SHA512:
6
- metadata.gz: ee0175a90dd63624ea349ee0605bc7b43bd501b37deb76bba392660106b370f42ab26c7ef0a00564e0593e834cc427ef2277fac662d1ce32636b1cac36d01918
7
- data.tar.gz: 0497d8cdf327cfffdbba9f65cca6a12c3b12718751f8ca2747cddadd4e84caef7eb9f0ef568460c0beb13542685ebc1391cfa3a8f15b6ee02bf1dcb96839afc6
6
+ metadata.gz: cf729a2b109bafa2598e55384f2c64e9d8ed064f86f8077f384e421e1be5be91fd9c0aae56c7bf9f10f1a86c087fd1c4dc2ce572719e9d67a1aa59f634f81254
7
+ data.tar.gz: 501be5a33044479639d4c5ed74fc883129370e215eadb23597ae4bc00e622df9ae7b396c3d5bc631cb3c00fbf4303b4286fb1f1a7d7e87e0c3af2057ee309391
@@ -1,5 +1,5 @@
1
1
  module Virtus
2
2
  module Mapper
3
- VERSION = "0.1.3"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
data/lib/virtus/mapper.rb CHANGED
@@ -7,13 +7,23 @@ HWIA = ActiveSupport::HashWithIndifferentAccess
7
7
  module Virtus
8
8
  module Mapper
9
9
 
10
+ attr_reader :mapped_attributes
11
+
10
12
  def initialize(attrs={})
11
- super(map_attributes!(HWIA.new(attrs)))
13
+ @mapped_attributes = HWIA.new(attrs)
14
+ super(prepare_attributes_for_assignment!(@mapped_attributes))
15
+ end
16
+
17
+ def extend_with(mod)
18
+ attr_set = attribute_set
19
+ self.extend(mod) # Virtus modifies attribute_set
20
+ set_attr_values(attribute_set.collect(&:name))
21
+ update_attribute_set(attr_set)
12
22
  end
13
23
 
14
24
  private
15
25
 
16
- def map_attributes!(attrs)
26
+ def prepare_attributes_for_assignment!(attrs)
17
27
  attrs.tap do |h|
18
28
  attributes_to_map_by_symbol(attrs).each do |att|
19
29
  h[att.name] = h.delete(from(att))
@@ -42,5 +52,21 @@ module Virtus
42
52
  def from(attribute)
43
53
  attribute.options[:from]
44
54
  end
55
+
56
+ def update_attribute_set(attr_set)
57
+ attr_set.merge(attribute_set)
58
+ self.attribute_set = attr_set
59
+ end
60
+
61
+ def attribute_set=(attr_set)
62
+ instance_variable_set(:@attribute_set, attr_set)
63
+ end
64
+
65
+ def set_attr_values(names)
66
+ attrs = prepare_attributes_for_assignment!(mapped_attributes)
67
+ names.each do |name|
68
+ self.send("#{name}=", attrs[name])
69
+ end
70
+ end
45
71
  end
46
72
  end
data/scratchpad.md ADDED
@@ -0,0 +1,9 @@
1
+ Scratchpad
2
+ ==========
3
+
4
+ - [ ] Is raw attributes the correct name. We do change them when they are
5
+ mapped, so raw is probably not correct. mapped_attributes
6
+
7
+ - [ ] #update_attributes
8
+
9
+ - [ ] Remove attrs arg from private methods, use raw_attributes
@@ -19,11 +19,27 @@ module Virtus
19
19
  from: lambda { |atts| atts[:address][:street] rescue '' }
20
20
  end
21
21
 
22
- class Narwhal
22
+ module Employment
23
+ include Virtus.module
24
+ include Virtus::Mapper
25
+
26
+ attribute :company, String, from: :business
27
+ attribute :job_title, String, from: :position
28
+ attribute :salary, Integer
29
+ end
30
+
31
+ module Traits
32
+ include Virtus.module
33
+ include Virtus::Mapper
34
+
35
+ attribute :eye_color, String, from: :eyecolor
36
+ end
37
+
38
+ class Dog
23
39
  include Virtus.model
24
40
  include Virtus::Mapper
25
41
 
26
- attribute :name, String, from: :narwhalmom
42
+ attribute :name, String, from: :shelter
27
43
  end
28
44
  end
29
45
  end
@@ -32,21 +48,24 @@ module Virtus
32
48
  let(:first_name) { 'John' }
33
49
  let(:last_name) { 'Doe' }
34
50
  let(:address) { '1122 Something Avenue' }
35
- let(:attrs) {
51
+ let(:person_attrs) {
36
52
  { person_id: person_id,
37
53
  first_name: first_name,
38
54
  surname: last_name,
39
55
  address: { 'street' => address } }
40
56
  }
41
- let(:mapper) { Examples::Person.new(attrs) }
57
+ let(:employment_attrs) {
58
+ { salary: 100, business: 'RentPath', position: 'Programmer' }
59
+ }
60
+ let(:person) { Examples::Person.new(person_attrs) }
42
61
 
43
62
  describe 'attribute with from option as symbol' do
44
63
  it 'translates key' do
45
- expect(mapper.last_name).to eq(last_name)
64
+ expect(person.last_name).to eq(last_name)
46
65
  end
47
66
 
48
67
  it 'does not create method from original key' do
49
- expect { mapper.surname }.to raise_error(NoMethodError)
68
+ expect { person.surname }.to raise_error(NoMethodError)
50
69
  end
51
70
 
52
71
  describe 'with attribute name as key' do
@@ -63,34 +82,114 @@ module Virtus
63
82
  describe 'attribute with from option as callable object' do
64
83
  it 'calls the object and passes the attributes hash' do
65
84
  callable = Examples::Person.attribute_set[:address].options[:from]
66
- expect(callable).to receive(:call) { attrs }
67
- Examples::Person.new(attrs)
85
+ expect(callable).to receive(:call) { person_attrs }
86
+ Examples::Person.new(person_attrs)
68
87
  end
69
88
 
70
89
  it 'sets attribute to result of call' do
71
- expect(mapper.address).to eq(address)
90
+ expect(person.address).to eq(address)
72
91
  end
73
92
  end
74
93
 
75
94
 
76
95
  describe 'attribute without from option' do
77
96
  it 'behaves as usual' do
78
- expect(mapper.first_name).to eq(first_name)
97
+ expect(person.first_name).to eq(first_name)
79
98
  end
80
99
  end
81
100
 
82
101
  it 'maps attributes with indifferent access' do
83
- mapper = Examples::Person.new({ person_id: 1,
102
+ person = Examples::Person.new({ person_id: 1,
84
103
  first_name: first_name,
85
104
  'surname' => last_name })
86
- expect(mapper.last_name).to eq('Doe')
105
+ expect(person.last_name).to eq('Doe')
87
106
  end
88
107
 
89
108
  describe 'given no arguments to constructor' do
90
109
  it 'does not raise error' do
91
- expect {
92
- Examples::Narwhal.new
93
- }.not_to raise_error
110
+ expect { Examples::Dog.new }.not_to raise_error
111
+ end
112
+ end
113
+
114
+ # describe '#mapped_attributes' do
115
+ # let(:person) { Examples::Person.new(person_attrs.merge({ unused: true })) }
116
+
117
+ # it 'preserves unused attributes' do
118
+ # expect(person.mapped_attributes[:unused]).to be true
119
+ # end
120
+
121
+ # it 'does not create instance methods for unused attributes' do
122
+ # expect { person.unused }.to raise_error(NoMethodError)
123
+ # end
124
+ # end
125
+
126
+ describe '#extend_with' do
127
+ describe 'for single extended module' do
128
+ let(:person) {
129
+ Examples::Person.new(person_attrs.merge(employment_attrs))
130
+ }
131
+
132
+ before do
133
+ person.extend_with(Examples::Employment)
134
+ end
135
+
136
+ it 'updates unmapped attribute values for extended modules' do
137
+ expect(person.salary).to eq(100)
138
+ end
139
+
140
+ it 'updates mapped attribute values for extended modules' do
141
+ expect(person.job_title).to eq('Programmer')
142
+ end
143
+
144
+ it 'adds module attributes to attribute_set' do
145
+ attr_names = person.instance_eval { attribute_set }.collect(&:name)
146
+ [:id,
147
+ :first_name,
148
+ :last_name,
149
+ :address,
150
+ :company,
151
+ :job_title,
152
+ :salary].each do |attr_name|
153
+ expect(attr_names).to include(attr_name)
154
+ end
155
+ end
156
+ end
157
+
158
+ describe 'for multiple extended modules' do
159
+ let(:person) {
160
+ Examples::Person.new(
161
+ person_attrs.merge(employment_attrs.merge({ eyecolor: 'green' }))
162
+ )
163
+ }
164
+
165
+ before do
166
+ person.extend_with(Examples::Employment)
167
+ person.extend_with(Examples::Traits)
168
+ end
169
+
170
+ it 'updates mapped attributes for last module extended' do
171
+ expect(person.eye_color).to eq('green')
172
+ end
173
+
174
+ it 'updates mapped attributes for first module extended' do
175
+ expect(person.salary).to eq(100)
176
+ expect(person.company).to eq('RentPath')
177
+ expect(person.job_title).to eq('Programmer')
178
+ end
179
+
180
+ it 'adds module attributes to attribute_set' do
181
+ attr_names = person.instance_eval { attribute_set }.collect(&:name)
182
+ [:id,
183
+ :first_name,
184
+ :last_name,
185
+ :address,
186
+ :company,
187
+ :job_title,
188
+ :salary,
189
+ :eye_color].each do |attr_name|
190
+ expect(attr_names).to include(attr_name)
191
+ end
192
+ end
94
193
  end
95
194
  end
96
195
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: virtus-mapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - RentPath
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-25 00:00:00.000000000 Z
11
+ date: 2014-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: virtus
@@ -109,6 +109,7 @@ files:
109
109
  - Rakefile
110
110
  - lib/virtus/mapper.rb
111
111
  - lib/virtus/mapper/version.rb
112
+ - scratchpad.md
112
113
  - spec/spec_helper.rb
113
114
  - spec/virtus/mapper_spec.rb
114
115
  - virtus-mapper.gemspec