virtus-mapper 0.1.3 → 0.2.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 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