yaoc 0.0.4 → 0.0.5

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: 409ba0cb455bbdea76b8dd9f32bd81c5d7d8a6bf
4
- data.tar.gz: 37de097336722ccd09c26c44f943a6161355ae9f
3
+ metadata.gz: 1a3e08de6de1dd93ced77b872cc67f802987d027
4
+ data.tar.gz: 01fa46d585b98a34f3c13fb118d259b6006a8d58
5
5
  SHA512:
6
- metadata.gz: 1258d989f4d14f28c806c45daac46516d0277e471906583ad999d68a662b09deb792118fc9675a06b9df50c12ecfa558a1631d5c2226d26009d10c16d485c389
7
- data.tar.gz: b3969999352325fe98045f0b2e5d3edd153f1b12915822a93a1b44f776893a2963cf943fed7103462c882b6a845df1c64f1e79404fabbee408dfc85e7956615a
6
+ metadata.gz: 045204c3589d7c9c683ba014503db36c6dab8165a34abd50a1e7157f1b28445136a7923a62d2b6b2506bdd6276fc2989fc0cfcdb7e6b725c45cafc4e9edcb05d
7
+ data.tar.gz: 31cd8c25c0f8a7d6dc1ecd960777fd34e1b9d2f3b9cb3b1663673724ae59d6aa4e446efe9730cf625c23e66e9b4af573d71db25cf3c78412efce0aac67577fb8
data/Guardfile CHANGED
@@ -6,6 +6,8 @@ guard :rspec, all_after_pass: true ,
6
6
 
7
7
  watch(%r{^spec/.+_spec\.rb$})
8
8
 
9
+ watch('lib/yaoc.rb') { "spec" }
10
+
9
11
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/unit/lib/#{m[1]}_spec.rb" }
10
12
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/integration/lib/#{m[1]}_spec.rb" }
11
13
 
data/README.md CHANGED
@@ -53,21 +53,15 @@ mapper = Yaoc::ObjectMapper.new(User, OldUser).tap do |mapper|
53
53
 
54
54
  rule to: :firstname,
55
55
  from: :fullname,
56
- converter: ->(source, result){ result.merge({firstname:
57
- source.fullname.split().first }) },
58
- reverse_converter: ->(source, result){ result.merge({fullname:
59
- "#{source.firstname} #{source.lastname}" }) }
56
+ converter: ->(source, result){ fill_result_with_value(result, :firstname, source.fullname.split().first) },
57
+ reverse_converter: ->(source, result){ fill_result_with_value(result, :fullname, "#{source.firstname} #{source.lastname}") }
60
58
 
61
59
  rule to: :lastname,
62
60
  from: :fullname,
63
- converter: ->(source, result){ result.merge({lastname: source.fullname.split().last }) },
61
+ converter: ->(source, result){ fill_result_with_value(result, :lastname, source.fullname.split().last ) },
64
62
  reverse_converter: ->(source, result){ result }
65
63
 
66
64
  rule to: :id
67
-
68
- # or
69
- # rule to: [:id, :foo, :bar, ...], from: [:rid, :rfoo], converter: [->(){}]
70
-
71
65
  end
72
66
  end
73
67
 
@@ -120,12 +114,12 @@ mapper = Yaoc::ObjectMapper.new(source, reverse_source).tap do |mapper|
120
114
 
121
115
  rule to: :firstname,
122
116
  from: :fullname,
123
- converter: ->(source, result){ result.merge({firstname: source.fullname.split().first }) },
124
- reverse_converter: ->(source, result){ result.merge({fullname: "#{source.firstname} #{source.lastname}" }) }
117
+ converter: ->(source, result){ fill_result_with_value(result, :firstname, source.fullname.split().first ) },
118
+ reverse_converter: ->(source, result){ fill_result_with_value(result, :fullname, "#{source.firstname} #{source.lastname}") }
125
119
 
126
120
  rule to: :lastname,
127
121
  from: :fullname,
128
- converter: ->(source, result){ result.merge({lastname: source.fullname.split().last }) },
122
+ converter: ->(source, result){ fill_result_with_value(result, :lastname, source.fullname.split().last) },
129
123
  reverse_converter: ->(source, result){ result }
130
124
 
131
125
  rule to: :id
@@ -169,8 +163,8 @@ mapper = Yaoc::ObjectMapper.new(User3, OldUser3).tap do |mapper|
169
163
  rule to: 1,
170
164
  from: :fullname,
171
165
 
172
- converter: ->(source, result){ result[1] = source.fullname.split().first },
173
- reverse_converter: ->(source, result){ result[1] = "#{source.firstname} #{source.lastname}" }
166
+ converter: ->(source, result){ fill_result_with_value(result, 1, source.fullname.split().first) },
167
+ reverse_converter: ->(source, result){ fill_result_with_value(result, 1, "#{source.firstname} #{source.lastname}") }
174
168
 
175
169
  rule to: 2,
176
170
  from: :fullname,
@@ -180,6 +174,7 @@ mapper = Yaoc::ObjectMapper.new(User3, OldUser3).tap do |mapper|
180
174
 
181
175
  rule to: 3, from: :r_role,
182
176
  reverse_to: 2, reverse_from: :role
177
+
183
178
  end
184
179
  end
185
180
 
@@ -200,6 +195,98 @@ puts mapper.dump(new_user3)
200
195
 
201
196
  ```
202
197
 
198
+ ### And how to use it with compositions?
199
+
200
+ ```ruby
201
+
202
+ User4 = Struct.new(:id, :firstname, :lastname, :roles) do
203
+ def initialize(params={})
204
+ super()
205
+
206
+ params.each do |attr, value|
207
+ self.public_send("#{attr}=", value)
208
+ end if params
209
+ end
210
+ end
211
+
212
+ OldUser4 = Struct.new(:o_id, :o_firstname, :o_lastname, :o_roles) do
213
+ def initialize(params={})
214
+ super()
215
+
216
+ params.each do |attr, value|
217
+ self.public_send("#{attr}=", value)
218
+ end if params
219
+ end
220
+ end
221
+
222
+
223
+ Role = Struct.new(:id, :name) do
224
+ def initialize(params={})
225
+ super()
226
+
227
+ params.each do |attr, value|
228
+ self.public_send("#{attr}=", value)
229
+ end if params
230
+ end
231
+ end
232
+
233
+ OldRole = Struct.new(:o_id, :o_name) do
234
+ def initialize(params={})
235
+ super()
236
+
237
+ params.each do |attr, value|
238
+ self.public_send("#{attr}=", value)
239
+ end if params
240
+ end
241
+ end
242
+
243
+
244
+ role_mapper = Yaoc::ObjectMapper.new(Role, OldRole).tap do |mapper|
245
+ mapper.add_mapping do
246
+ fetcher :public_send
247
+
248
+ rule to: :id, from: :o_id
249
+ rule to: :name, from: :o_name
250
+
251
+ end
252
+ end
253
+
254
+ user_mapper = Yaoc::ObjectMapper.new(User4, OldUser4).tap do |mapper|
255
+ mapper.add_mapping do
256
+ fetcher :public_send
257
+
258
+ rule to: [:id, :firstname, :lastname],
259
+ from: [:o_id, :o_firstname, :o_lastname]
260
+
261
+ rule to: :roles,
262
+ from: :o_roles,
263
+ object_converter: role_mapper,
264
+ is_collection: true
265
+
266
+ end
267
+ end
268
+
269
+
270
+ old_user4 = OldUser4.new(o_id: 1,
271
+ o_firstname: "firstname",
272
+ o_lastname:"lastname",
273
+ o_roles: [OldRole.new(o_id: 1, o_name: "admin"), OldRole.new(o_id: 2, o_name: "guest")] )
274
+ new_user4 = user_mapper.load(old_user4)
275
+
276
+ puts old_user4
277
+ puts new_user4
278
+
279
+ puts user_mapper.dump(new_user4)
280
+
281
+ #<struct OldUser4 o_id=1, o_firstname="firstname", o_lastname="lastname",
282
+ # o_roles=[#<struct OldRole o_id=1, o_name="admin">, #<struct OldRole o_id=2, o_name="guest">]>
283
+ #<struct User4 id=1, firstname="firstname", lastname="lastname",
284
+ # roles=[#<struct Role id=1, name="admin">, #<struct Role id=2, name="guest">]>
285
+ #<struct OldUser4 o_id=1, o_firstname="firstname", o_lastname="lastname",
286
+ # o_roles=[#<struct OldRole o_id=1, o_name="admin">, #<struct OldRole o_id=2, o_name="guest">]>
287
+
288
+ ```
289
+
203
290
  ## Contributing
204
291
 
205
292
  1. Fork it ( http://github.com/slowjack2k/yaoc/fork )
@@ -1,7 +1,56 @@
1
1
  module Yaoc
2
2
 
3
+ class NormalizedParameters
4
+ attr_accessor :to_s, :from_s, :converter_s
5
+
6
+ def initialize(to, from, converter, object_converter, is_collection)
7
+ self.to_s = Array(to)
8
+ self.from_s = Array(from)
9
+ self.converter_s = Array(converter)
10
+
11
+ object_converter_s = Array(object_converter)
12
+ is_collection_s = Array(is_collection)
13
+
14
+ self.to_s.each_with_index do |to, index|
15
+ from_s[index] ||= to
16
+ end
17
+
18
+ object_converter_s.each_with_index do |object_converter, index|
19
+ converter_s[index] = converter_to_proc(to_s[index], from_s[index], object_converter, !!is_collection_s[index])
20
+ end
21
+
22
+ end
23
+
24
+ def each
25
+ return to_enum(__callee__) unless block_given?
26
+
27
+ self.to_s.each_with_index do |to, index|
28
+ yield to, from_s[index] , converter_s[index]
29
+ end
30
+ end
31
+
32
+ def converter_to_proc(to, from, converter, is_collection)
33
+ ->(source, result){
34
+ object_to_convert = source.public_send(fetcher, from)
35
+ converted_object = nil
36
+
37
+ if is_collection
38
+ converted_object = object_to_convert.map(&converter)
39
+ else
40
+ converter_as_proc = converter.to_proc
41
+ converted_object = converter_as_proc.call(object_to_convert)
42
+ end
43
+
44
+ fill_result_with_value(result, to, converted_object)
45
+ }
46
+ end
47
+
48
+ end
49
+
50
+
3
51
  class ConverterBuilder
4
- attr_accessor :build_commands, :command_order, :strategy, :all_commands_applied
52
+ attr_accessor :build_commands, :command_order,
53
+ :strategy, :all_commands_applied
5
54
 
6
55
  def initialize(command_order=:recorded_order, fetcher=:fetch)
7
56
  self.build_commands = []
@@ -16,15 +65,11 @@ module Yaoc
16
65
  apply_commands!
17
66
  end
18
67
 
19
- def rule(to: nil, from: to, converter: nil)
68
+ def rule(to: nil, from: to, converter: nil, object_converter: nil, is_collection: nil)
20
69
  self.all_commands_applied = false
21
70
 
22
- to_s = Array(to)
23
- from_s = Array(from)
24
- converter_s = Array(converter)
25
-
26
- to_s.each_with_index do |to, index|
27
- build_commands.push ->{ converter_class.map(to, from_s[index] || to, converter_s[index]) }
71
+ NormalizedParameters.new(to, from, converter, object_converter, is_collection).each do |to, from, converter|
72
+ build_commands.push ->{ converter_class.map(to, from , converter) }
28
73
  end
29
74
  end
30
75
 
@@ -35,9 +80,9 @@ module Yaoc
35
80
  build_commands_ordered.each &:call
36
81
  end
37
82
 
38
- def converter(fetch_able)
83
+ def converter(fetch_able, target_source=nil)
39
84
  raise "BuildCommandsNotExecuted" unless self.all_commands_applied?
40
- converter_class.new(fetch_able, fetcher)
85
+ converter_class.new(fetch_able, fetcher, target_source || ->(attrs){ attrs})
41
86
  end
42
87
 
43
88
  def fetcher=(new_fetcher)
@@ -47,10 +92,11 @@ module Yaoc
47
92
  protected
48
93
 
49
94
  def converter_class
50
- @converter_class ||= Struct.new(:to_convert, :fetcher) do
51
- include MappingBase
95
+ @converter_class ||= Struct.new(:to_convert, :fetcher, :target_source) do
96
+ include MappingToClass
97
+
52
98
  end.tap do |new_class|
53
- new_class.send(:include, strategy_module)
99
+ new_class.mapping_strategy = strategy_module
54
100
  end
55
101
  end
56
102
 
@@ -2,12 +2,30 @@ module Yaoc
2
2
  module MappingBase
3
3
  include AbstractType
4
4
 
5
-
6
5
  def self.included(other)
7
6
  other.extend(ClassMethods)
8
7
  end
9
8
 
10
- abstract_method :call
9
+ def to_proc
10
+ ->(to_convert){
11
+ old_to_convert = self.to_convert
12
+ begin
13
+ self.to_convert = to_convert
14
+ call
15
+ ensure
16
+ self.to_convert = old_to_convert
17
+ end
18
+ }
19
+ end
20
+
21
+ def call
22
+ self.class.mapping_strategy.call(self)
23
+ end
24
+
25
+ def fill_result_with_value(result, key, value)
26
+ result.tap{|taped_result| taped_result[key] = value}
27
+ end
28
+
11
29
 
12
30
  def converter_methods
13
31
  self.class.converter_methods
@@ -20,7 +38,19 @@ module Yaoc
20
38
  module ClassMethods
21
39
  include AbstractType
22
40
 
23
- abstract_method :converter_proc
41
+ def converter_proc(to, from)
42
+ -> (to_convert, result){
43
+ fill_result_with_value(result, to, to_convert.public_send(fetcher, from))
44
+ }
45
+ end
46
+
47
+ def mapping_strategy=(new_strat)
48
+ @mapping_strategy = new_strat
49
+ end
50
+
51
+ def mapping_strategy
52
+ @mapping_strategy
53
+ end
24
54
 
25
55
  def map(to, from, block=nil)
26
56
  class_private_module(:Mapping).tap do |mod|
@@ -0,0 +1,32 @@
1
+ module Yaoc
2
+ module MappingToClass
3
+
4
+ def self.included(other)
5
+ other.send(:include, MappingBase)
6
+ other.send(:include, InstanceMethods)
7
+ end
8
+
9
+ module InstanceMethods
10
+ def call(*args)
11
+ create_target(super)
12
+ end
13
+
14
+ def source_method
15
+ self.target_source.respond_to?(:call) ? :call : :new
16
+ end
17
+
18
+ def create_target(args)
19
+ if args.is_a? Array
20
+ self.target_source.send(source_method, *args)
21
+ else
22
+ self.target_source.send(source_method, args)
23
+ end
24
+ end
25
+
26
+ def to_a # wenn included into struct's Array(...) call's to_a
27
+ [self]
28
+ end
29
+ end
30
+
31
+ end
32
+ end
@@ -3,19 +3,17 @@ module Yaoc
3
3
  class ObjectMapper
4
4
  attr_accessor :load_result_source, :dump_result_source
5
5
 
6
- def initialize(load_result_source, dump_result_source=->(attrs){ attrs})
7
- self.load_result_source = load_result_source.respond_to?(:call) ? load_result_source : ->(*attrs){load_result_source.new(*attrs)}
8
- self.dump_result_source = dump_result_source.respond_to?(:call) ? dump_result_source : ->(*attrs){dump_result_source.new(*attrs)}
6
+ def initialize(load_result_source, dump_result_source=nil)
7
+ self.load_result_source = load_result_source
8
+ self.dump_result_source = dump_result_source
9
9
  end
10
10
 
11
11
  def load(fetch_able)
12
- converter_result = converter(fetch_able).call()
13
- call_constructor(load_result_source, converter_result)
12
+ converter(fetch_able).call()
14
13
  end
15
14
 
16
15
  def dump(object)
17
- converter_result = reverse_converter(object).call()
18
- call_constructor(dump_result_source, converter_result)
16
+ reverse_converter(object).call()
19
17
  end
20
18
 
21
19
  def add_mapping(&block)
@@ -23,34 +21,44 @@ module Yaoc
23
21
  apply_commands
24
22
  end
25
23
 
26
- protected
24
+ def converter(fetch_able=nil)
25
+ converter_builder.converter(fetch_able, load_result_source)
26
+ end
27
27
 
28
- def call_constructor(call_able, args)
29
- if args.is_a? Array
30
- call_able.call(*args)
31
- else
32
- call_able.call(args)
33
- end
28
+ def reverse_converter(fetch_able=nil)
29
+ reverse_converter_builder.converter(fetch_able, dump_result_source)
34
30
  end
35
31
 
32
+ protected
33
+
36
34
  def apply_commands
37
35
  converter_builder.apply_commands!
38
36
  reverse_converter_builder.apply_commands!
39
37
  end
40
38
 
41
39
  def rule(to: nil, from: to, converter: nil,
42
- reverse_to: from, reverse_from: to, reverse_converter: nil)
40
+ reverse_to: from,
41
+ reverse_from: to,
42
+ reverse_converter: nil,
43
+ object_converter: nil,
44
+ is_collection: nil)
45
+
46
+ object_converter = Array(object_converter)
43
47
 
44
48
  converter_builder.rule(
45
49
  to: to,
46
50
  from: from,
47
51
  converter: converter,
52
+ object_converter: object_converter.map(&:converter),
53
+ is_collection: is_collection,
48
54
  )
49
55
 
50
56
  reverse_converter_builder.rule(
51
57
  to: reverse_to,
52
58
  from: reverse_from,
53
59
  converter: reverse_converter,
60
+ object_converter: object_converter.map(&:reverse_converter),
61
+ is_collection: is_collection,
54
62
  )
55
63
  end
56
64
 
@@ -70,14 +78,6 @@ module Yaoc
70
78
  reverse_converter_builder.strategy = new_strategy
71
79
  end
72
80
 
73
- def converter(fetch_able)
74
- converter_builder.converter(fetch_able)
75
- end
76
-
77
- def reverse_converter(fetch_able)
78
- reverse_converter_builder.converter(fetch_able)
79
- end
80
-
81
81
  def converter_builder
82
82
  @converter_builder ||= Yaoc::ConverterBuilder.new()
83
83
  end
@@ -1,25 +1,15 @@
1
1
  module Yaoc
2
2
  module Strategies
3
3
  module ToArrayMapping
4
- def self.included(other)
5
- other.extend(ClassMethods)
6
- end
7
4
 
8
- def call
5
+ def self.call(conv_object)
9
6
  [].tap do |result|
10
- converter_methods.each do |method_name|
11
- self.public_send(method_name, to_convert, result)
7
+ conv_object.converter_methods.each do |method_name|
8
+ conv_object.public_send(method_name, conv_object.to_convert, result)
12
9
  end
13
10
  end
14
11
  end
15
12
 
16
- module ClassMethods
17
- def converter_proc(to, from)
18
- -> (to_convert, result){
19
- result[to] = to_convert.public_send(fetcher, from)
20
- }
21
- end
22
- end
23
13
  end
24
14
  end
25
15
  end
@@ -1,23 +1,13 @@
1
1
  module Yaoc
2
2
  module Strategies
3
3
  module ToHashMapping
4
- def self.included(other)
5
- other.extend(ClassMethods)
6
- end
7
4
 
8
- def call
9
- converter_methods.reduce({}) do |result, method_name|
10
- self.public_send(method_name, to_convert, result)
5
+ def self.call(conv_object)
6
+ conv_object.converter_methods.reduce({}) do |result, method_name|
7
+ conv_object.public_send(method_name, conv_object.to_convert, result)
11
8
  end
12
9
  end
13
10
 
14
- module ClassMethods
15
- def converter_proc(to, from)
16
- -> (to_convert, result){
17
- result.merge({to => to_convert.public_send(fetcher, from)})
18
- }
19
- end
20
- end
21
11
  end
22
12
  end
23
13
  end
data/lib/yaoc/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Yaoc
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
data/lib/yaoc.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require "yaoc/version"
2
2
  require 'abstract_type'
3
3
  require 'yaoc/mapping_base'
4
+ require 'yaoc/mapping_to_class'
4
5
 
5
6
  Dir[File.join(File.expand_path(__dir__ ), "yaoc/strategies/*.rb")].each { |f| require f }
6
7
 
@@ -8,5 +9,5 @@ require 'yaoc/converter_builder'
8
9
  require 'yaoc/object_mapper'
9
10
 
10
11
  module Yaoc
11
- # Your code goes here...
12
+
12
13
  end
@@ -12,8 +12,8 @@ feature "Map objects", %q{
12
12
  fetcher :public_send
13
13
  reverse_fetcher :public_send
14
14
  rule to: :name,
15
- converter: ->(source, result){ result.merge({name: "#{source[:name]} Hello World"}) },
16
- reverse_converter: ->(source, result){ result.merge({name: source.name}) }
15
+ converter: ->(source, result){ fill_result_with_value(result, :name, "#{source[:name]} Hello World") },
16
+ reverse_converter: ->(source, result){ fill_result_with_value(result, :name, source.name) }
17
17
  rule to: :role, from: :fullrolename
18
18
  rule to: :id
19
19
  rule to: [:foo, :bar]
@@ -0,0 +1,173 @@
1
+ require "spec_helper"
2
+
3
+ feature "Map objects reusing other existing converters", %q{
4
+ In order to map objects with other converters
5
+ as a lib user
6
+ I want to map object from an input object to an output object and reverse with a given converter
7
+ } do
8
+
9
+
10
+ given(:new_role_class){
11
+ Struct.new(:id, :name) do
12
+ include Equalizer.new(:id, :name)
13
+
14
+ def initialize(params={})
15
+ super()
16
+
17
+ params.each do |attr, value|
18
+ self.public_send("#{attr}=", value)
19
+ end if params
20
+ end
21
+ end
22
+ }
23
+
24
+ given(:old_role_class){
25
+ Struct.new(:o_id, :o_name) do
26
+ include Equalizer.new(:o_id, :o_name)
27
+
28
+ def initialize(params={})
29
+ super()
30
+
31
+ params.each do |attr, value|
32
+ self.public_send("#{attr}=", value)
33
+ end if params
34
+ end
35
+ end
36
+ }
37
+
38
+ given(:role_converter){
39
+ Yaoc::ObjectMapper.new(new_role_class, old_role_class).tap do |mapper|
40
+ mapper.add_mapping do
41
+ fetcher :public_send
42
+
43
+ rule to: [:id, :name],
44
+ from: [:o_id, :o_name]
45
+
46
+ end
47
+ end
48
+ }
49
+
50
+ given(:new_user_class){
51
+ Struct.new(:id, :firstname, :lastname, :roles) do
52
+ include Equalizer.new(:id, :firstname, :lastname, :roles)
53
+
54
+ def initialize(params={})
55
+ super()
56
+
57
+ params.each do |attr, value|
58
+ self.public_send("#{attr}=", value)
59
+ end if params
60
+ end
61
+ end
62
+ }
63
+
64
+ given(:old_user_class){
65
+ Struct.new(:o_id, :o_firstname, :o_lastname, :o_roles) do
66
+ include Equalizer.new(:o_id, :o_firstname, :o_lastname, :o_roles)
67
+
68
+ def initialize(params={})
69
+ super()
70
+
71
+ params.each do |attr, value|
72
+ self.public_send("#{attr}=", value)
73
+ end if params
74
+ end
75
+ end
76
+ }
77
+
78
+ given(:user_converter){
79
+ other_converter = role_converter
80
+ is_col = is_collection
81
+
82
+ Yaoc::ObjectMapper.new(new_user_class, old_user_class).tap do |mapper|
83
+ mapper.add_mapping do
84
+ fetcher :public_send
85
+
86
+ rule to: [:id, :firstname, :lastname],
87
+ from: [:o_id, :o_firstname, :o_lastname]
88
+
89
+ rule to: :roles,
90
+ from: :o_roles,
91
+ object_converter: other_converter,
92
+ is_collection: is_col
93
+ end
94
+ end
95
+ }
96
+
97
+
98
+ context "composition is a collection" do
99
+ given(:is_collection){
100
+ true
101
+ }
102
+
103
+ given(:old_user) {
104
+ old_user_class.new(
105
+ o_id: "user_1",
106
+ o_firstname: "o firstname",
107
+ o_lastname: "o lastname",
108
+ o_roles: [
109
+ old_role_class.new(o_id: "role_1", o_name: "admin"),
110
+ old_role_class.new(o_id: "role_2", o_name: "ruth"),
111
+ old_role_class.new(o_id: "role_3", o_name: "guest"),
112
+ ]
113
+ )
114
+ }
115
+
116
+ given(:expected_new_user) {
117
+ new_user_class.new(
118
+ id: "user_1",
119
+ firstname: "o firstname",
120
+ lastname: "o lastname",
121
+ roles: [
122
+ new_role_class.new(id: "role_1", name: "admin"),
123
+ new_role_class.new(id: "role_2", name: "ruth"),
124
+ new_role_class.new(id: "role_3", name: "guest"),
125
+ ]
126
+ )
127
+ }
128
+
129
+ scenario "creates a new user from the old one" do
130
+ expect(user_converter.load(old_user)).to eq expected_new_user
131
+ end
132
+
133
+ scenario "dumps an result object as result object" do
134
+ expect(user_converter.dump(expected_new_user)).to eq old_user
135
+ end
136
+
137
+ end
138
+
139
+ context "composition is a single value" do
140
+ given(:is_collection){
141
+ false
142
+ }
143
+
144
+ given(:old_user) {
145
+ old_user_class.new(
146
+ o_id: "user_1",
147
+ o_firstname: "o firstname",
148
+ o_lastname: "o lastname",
149
+ o_roles: old_role_class.new(o_id: "role_1", o_name: "admin, ruth, guest")
150
+
151
+ )
152
+ }
153
+
154
+ given(:expected_new_user) {
155
+ new_user_class.new(
156
+ id: "user_1",
157
+ firstname: "o firstname",
158
+ lastname: "o lastname",
159
+ roles: new_role_class.new(id: "role_1", name: "admin, ruth, guest")
160
+ )
161
+ }
162
+
163
+ scenario "creates a new user from the old one" do
164
+ expect(user_converter.load(old_user)).to eq expected_new_user
165
+ end
166
+
167
+ scenario "dumps an result object as result object" do
168
+ expect(user_converter.dump(expected_new_user)).to eq old_user
169
+ end
170
+
171
+ end
172
+
173
+ end
@@ -1,6 +1,6 @@
1
1
  require "spec_helper"
2
2
 
3
- feature "Map objects", %q{
3
+ feature "Map objects to classes with positional constructors", %q{
4
4
  In order to map objects with positional constructors
5
5
  as a lib user
6
6
  I want to map object from an input object to an output object and reverse with a given mapping strategy
@@ -0,0 +1,58 @@
1
+ require "spec_helper"
2
+
3
+ describe Yaoc::ConverterBuilder do
4
+ subject{
5
+ ot = other_converter
6
+ is_col = is_collection
7
+
8
+ Yaoc::ConverterBuilder.new().tap{|converter|
9
+ converter.add_mapping do
10
+ fetch_with :[]
11
+ rule to: :id,
12
+ from: :name,
13
+ is_collection: is_col,
14
+ object_converter: ot
15
+ end
16
+ }
17
+
18
+ }
19
+
20
+ let(:other_converter){
21
+ Class.new() do
22
+ def to_proc
23
+ @proc ||= ->(index, *args){
24
+ [nil, nil, :my_result_1, nil, :my_result_2][index]
25
+ }
26
+ end
27
+
28
+ def to_a
29
+ [self]
30
+ end
31
+
32
+ end.new
33
+ }
34
+
35
+ let(:is_collection){
36
+ false
37
+ }
38
+
39
+ describe "#converter_to_proc" do
40
+
41
+ it "creates a converter proc" do
42
+ expect(other_converter.to_proc).to receive(:call).with(2).and_return(:my_result)
43
+ expect(subject.converter(nil, nil).map_0000_name_to_id({:name => 2},{})).to eq(id: :my_result)
44
+ end
45
+
46
+ context "value to convert is a collection" do
47
+ let(:is_collection){
48
+ true
49
+ }
50
+
51
+ it "creates a converter proc for collections" do
52
+ expect(subject.converter(nil, nil).map_0000_name_to_id({:name => [2, 4]},{})).to eq(id: [:my_result_1, :my_result_2])
53
+ end
54
+
55
+ end
56
+ end
57
+
58
+ end
@@ -16,8 +16,10 @@ describe Yaoc::ConverterBuilder do
16
16
  double("converter", call: nil)
17
17
  }
18
18
 
19
- describe ".new" do
19
+ describe "#command_order" do
20
+
20
21
  it "applies command in recorded order as default" do
22
+ subject.command_order = :recorded_order
21
23
 
22
24
  expect(converter_class).to receive(:map).ordered.with(:id, :id, nil)
23
25
  expect(converter_class).to receive(:map).ordered.with(:name, :name, nil)
@@ -30,10 +32,7 @@ describe Yaoc::ConverterBuilder do
30
32
  end
31
33
 
32
34
  it "applies command in reverse recorded order when wanted" do
33
- subject = Yaoc::ConverterBuilder.new(:reverse_order).tap{|converter|
34
- converter.stub(:converter_class).and_return(converter_class)
35
- }
36
-
35
+ subject.command_order = :reverse_order
37
36
 
38
37
  expect(converter_class).to receive(:map).ordered.with(:name, :name, nil)
39
38
  expect(converter_class).to receive(:map).ordered.with(:id, :id, nil)
@@ -103,6 +102,29 @@ describe Yaoc::ConverterBuilder do
103
102
  from: [:r_id]
104
103
  end
105
104
  end
105
+
106
+ it "supports the use of a object converter" do
107
+ expect(converter_class).to receive(:map).ordered.with(:id, :id, kind_of(Proc))
108
+ other_converter = :some_converter
109
+
110
+ subject.add_mapping do
111
+ rule to: :id,
112
+ object_converter: other_converter
113
+ end
114
+
115
+ end
116
+
117
+ it "supports the collection flag for object converters" do
118
+ expect(converter_class).to receive(:map).ordered.with(:id, :id, kind_of(Proc))
119
+ other_converter = :some_converter
120
+
121
+ subject.add_mapping do
122
+ rule to: :id,
123
+ is_collection: true,
124
+ object_converter: other_converter
125
+ end
126
+
127
+ end
106
128
  end
107
129
 
108
130
  describe "#converter" do
@@ -112,7 +134,7 @@ describe Yaoc::ConverterBuilder do
112
134
  with_strategy :to_array_mapping
113
135
  end
114
136
 
115
- expect(subject.converter({})).to be_kind_of Yaoc::Strategies::ToArrayMapping
137
+ expect(subject.send(:converter_class).mapping_strategy).to eq(Yaoc::Strategies::ToArrayMapping)
116
138
  end
117
139
 
118
140
  it "raises an exception when not all commands are applied" do
@@ -122,4 +144,5 @@ describe Yaoc::ConverterBuilder do
122
144
  expect{subject.converter({})}.to raise_exception
123
145
  end
124
146
  end
147
+
125
148
  end
@@ -5,18 +5,12 @@ describe Yaoc::MappingBase do
5
5
  Struct.new(:to_convert) do
6
6
  include Yaoc::MappingBase
7
7
 
8
- def self.converter_proc(to, from)
9
- -> (to_convert, result){
10
- [to, from, to_convert, result]
11
- }
12
- end
13
-
14
- def call
15
- result = :my_result
16
- converter_methods.map do |method_name|
17
- self.public_send(method_name, to_convert, result)
8
+ self.mapping_strategy = ->(obj){
9
+ result = {}
10
+ obj.converter_methods.map do |method_name|
11
+ obj.public_send(method_name, obj.to_convert, result)
18
12
  end
19
- end
13
+ }
20
14
 
21
15
  end
22
16
  }
@@ -34,8 +28,8 @@ describe Yaoc::MappingBase do
34
28
  subject.map(:foo, :bar)
35
29
  subject.map(:bar, :foo)
36
30
 
37
- expect(subject.new(:my_to_convert).call()).to eq [[:foo, :bar, :my_to_convert, :my_result],
38
- [:bar, :foo, :my_to_convert, :my_result]]
31
+ expect(subject.new({bar: :my_to_convert, foo: :my_result}).call()).to eq [{:foo=>:my_to_convert, :bar=>:my_result},
32
+ {:foo=>:my_to_convert, :bar=>:my_result}]
39
33
  end
40
34
 
41
35
  it "uses my converter when provided" do
@@ -59,20 +53,6 @@ describe Yaoc::MappingBase do
59
53
  Struct.new(:to_convert) do
60
54
  include Yaoc::MappingBase
61
55
 
62
- def self.create_block(to, from)
63
- -> (to_convert, result){
64
- [to, from, to_convert, result]
65
- }
66
- end
67
-
68
- def call
69
- result = nil
70
-
71
- converter_methods.map do |method_name|
72
- self.public_send(method_name, to_convert, result)
73
- end
74
- end
75
-
76
56
  def fetcher
77
57
  "my_fetcher"
78
58
  end
@@ -90,4 +70,48 @@ describe Yaoc::MappingBase do
90
70
 
91
71
  end
92
72
 
73
+ describe "#call" do
74
+ it "delegates execution to strategy" do
75
+ mapper = subject.new()
76
+
77
+ expect(subject.mapping_strategy).to receive(:call).with mapper
78
+
79
+ mapper.call
80
+ end
81
+ end
82
+
83
+ describe "#to_proc" do
84
+ it "creates a wrapper around call" do
85
+ mapper = subject.new()
86
+ mapper_as_proc = mapper.to_proc
87
+ expect(mapper).to receive :call
88
+
89
+ mapper_as_proc.call(:some_thing)
90
+ end
91
+
92
+ it "changes 'to_convert' temporary" do
93
+ mapper = subject.new(:old_some_thing)
94
+ mapper_as_proc = mapper.to_proc
95
+
96
+ expect(mapper).to receive(:to_convert=).ordered.with(:some_thing)
97
+ expect(mapper).to receive(:to_convert=).ordered.with(:old_some_thing)
98
+
99
+ mapper_as_proc.call(:some_thing)
100
+ end
101
+
102
+ it "changes 'to_convert' even when a exception occurs" do
103
+ mapper = subject.new(:old_some_thing)
104
+ mapper_as_proc = mapper.to_proc
105
+
106
+ mapper.stub(:call) do
107
+ raise "MyException"
108
+ end
109
+
110
+ expect(mapper).to receive(:to_convert=).ordered.with(:some_thing)
111
+ expect(mapper).to receive(:to_convert=).ordered.with(:old_some_thing)
112
+
113
+ expect{mapper_as_proc.call(:some_thing)}.to raise_error "MyException"
114
+ end
115
+ end
116
+
93
117
  end
@@ -0,0 +1,53 @@
1
+ require "spec_helper"
2
+
3
+ describe Yaoc::MappingToClass do
4
+ subject{
5
+ Struct.new(:target_source) do
6
+ include Yaoc::MappingToClass
7
+
8
+ self.mapping_strategy = ->(obj){
9
+ [1]
10
+ }
11
+
12
+ end.new(expected_class)
13
+ }
14
+
15
+ let(:expected_class){
16
+ Struct.new(:id)
17
+ }
18
+
19
+ describe "#call" do
20
+ it "creates on object of the wanted kind" do
21
+ expect(subject.call).to be_kind_of expected_class
22
+ end
23
+
24
+ it "can use a lambda for creation" do
25
+ creator = ->(*args){}
26
+ expect(creator).to receive :call
27
+ subject.target_source = creator
28
+ subject.call
29
+ end
30
+
31
+
32
+ it "splashes args when conversion result is an array" do
33
+ creator = ->(*args){}
34
+ subject.class.mapping_strategy = ->(obj){
35
+ [1, 2]
36
+ }
37
+
38
+ expect(creator).to receive(:call).with(1,2)
39
+
40
+ subject.target_source = creator
41
+
42
+ subject.call
43
+ end
44
+ end
45
+
46
+ describe "#to_a" do
47
+ it "satisfies Array(*) when included into structs" do
48
+ expect(subject.to_a).to eq ([subject])
49
+ end
50
+ end
51
+
52
+
53
+ end
@@ -24,11 +24,26 @@ describe Yaoc::ObjectMapper do
24
24
  double("reverse_converter", call: nil)
25
25
  }
26
26
 
27
+ let(:expected_default_params){
28
+ {
29
+ to: :id,
30
+ from: :id,
31
+ converter: nil,
32
+ object_converter: [],
33
+ is_collection: nil
34
+ }
35
+ }
36
+
27
37
  describe "#add_mapping" do
28
38
 
29
39
  it "creates a converter" do
40
+ expected_params = expected_default_params.merge(
41
+ to: :id,
42
+ from: :id2,
43
+ converter: :some_proc
44
+ )
30
45
 
31
- expect(converter_builder).to receive(:rule).with(to: :id, from: :id2, converter: :some_proc)
46
+ expect(converter_builder).to receive(:rule).with(expected_params)
32
47
 
33
48
  subject.add_mapping do
34
49
  rule to: :id,
@@ -40,8 +55,13 @@ describe Yaoc::ObjectMapper do
40
55
  end
41
56
 
42
57
  it "creates a revers converter" do
58
+ expected_params = expected_default_params.merge(
59
+ to: :id2,
60
+ from: :id,
61
+ converter: :some_reverse_proc
62
+ )
43
63
 
44
- expect(reverse_converter_builder).to receive(:rule).with(to: :id2, from: :id, converter: :some_reverse_proc)
64
+ expect(reverse_converter_builder).to receive(:rule).with(expected_params)
45
65
 
46
66
  subject.add_mapping do
47
67
  rule to: :id,
@@ -52,9 +72,42 @@ describe Yaoc::ObjectMapper do
52
72
 
53
73
  end
54
74
 
75
+ it "allows to use another converter as converter" do
76
+ converter_double = double("converter")
77
+
78
+ expected_params = expected_default_params.merge(
79
+ from: :id2,
80
+ object_converter: [converter_double],
81
+ is_collection: false
82
+ )
83
+
84
+ expected_params_reverse = expected_default_params.merge(
85
+ to: :id2,
86
+ from: :id,
87
+ object_converter: [converter_double],
88
+ is_collection: false
89
+ )
90
+
91
+
92
+ expect(converter_builder).to receive(:rule).with(expected_params)
93
+ expect(reverse_converter_builder).to receive(:rule).with(expected_params_reverse)
94
+
95
+ expect(converter_double).to receive(:converter).and_return(converter_double)
96
+ expect(converter_double).to receive(:reverse_converter).and_return(converter_double)
97
+
98
+
99
+ subject.add_mapping do
100
+ rule to: :id,
101
+ from: :id2,
102
+ is_collection: false,
103
+ object_converter: converter_double
104
+ end
105
+ end
106
+
55
107
  it "uses defaults" do
56
- expect(converter_builder).to receive(:rule).with(to: :id, from: :id, converter: nil)
57
- expect(reverse_converter_builder).to receive(:rule).with(to: :id, from: :id, converter: nil)
108
+ expect(converter_builder).to receive(:rule).with(expected_default_params)
109
+
110
+ expect(reverse_converter_builder).to receive(:rule).with(expected_default_params)
58
111
 
59
112
  subject.add_mapping do
60
113
  rule to: :id
@@ -63,7 +116,12 @@ describe Yaoc::ObjectMapper do
63
116
  end
64
117
 
65
118
  it "accepts a reverse mapping for from and to" do
66
- expect(reverse_converter_builder).to receive(:rule).with(to: :id_r, from: :id_r, converter: nil)
119
+ expected_params = expected_default_params.merge(
120
+ to: :id_r,
121
+ from: :id_r,
122
+ )
123
+
124
+ expect(reverse_converter_builder).to receive(:rule).with(expected_params)
67
125
 
68
126
  subject.add_mapping do
69
127
  rule to: :id, reverse_to: :id_r, reverse_from: :id_r
@@ -78,7 +136,6 @@ describe Yaoc::ObjectMapper do
78
136
  rule to: :id
79
137
  end
80
138
 
81
-
82
139
  end
83
140
 
84
141
  it "allows to set a reverse_fetcher" do
@@ -107,30 +164,23 @@ describe Yaoc::ObjectMapper do
107
164
  rule to: :id, from: 0
108
165
  end
109
166
  end
167
+
110
168
  end
111
169
 
112
170
  describe "#load" do
113
- it "creates an object of result_class kind" do
114
- data = {id: 1}
115
-
116
- converter.stub(call: data)
171
+ it "creates an object of result class kind" do
172
+ expect(converter).to receive(:call)
117
173
 
118
- expect(subject.load_result_source).to receive(:call).with(data)
119
-
120
- subject.load(data)
174
+ subject.load({})
121
175
  end
122
176
  end
123
177
 
124
178
  describe "#dump" do
125
179
 
126
180
  it "dump the object as an wanted object" do
127
- data = {id: 1}
128
-
129
- reverse_converter.stub(call: data)
130
-
131
- expect(subject.dump_result_source).to receive(:call).with(data)
181
+ expect(reverse_converter).to receive(:call)
132
182
 
133
- subject.dump(data)
183
+ subject.dump({})
134
184
  end
135
185
 
136
186
  end
@@ -4,7 +4,7 @@ describe Yaoc::Strategies::ToArrayMapping do
4
4
  subject{
5
5
  Struct.new(:to_convert) do
6
6
  include Yaoc::MappingBase
7
- include Yaoc::Strategies::ToArrayMapping
7
+ self.mapping_strategy = Yaoc::Strategies::ToArrayMapping
8
8
  end
9
9
  }
10
10
 
@@ -32,7 +32,7 @@ describe Yaoc::Strategies::ToArrayMapping do
32
32
 
33
33
  it "uses my converter proc" do
34
34
  subject.map(0, :id)
35
- subject.map(3, :fullname, ->(source, result){ result[3] = "#{source.fetch(:name)} Hello World" })
35
+ subject.map(3, :fullname, ->(source, result){ fill_result_with_value(result, 3, "#{source.fetch(:name)} Hello World") })
36
36
 
37
37
  ext_expectation = expected_array.clone
38
38
  ext_expectation[3] = "#{ext_expectation[1]} Hello World"
@@ -4,7 +4,7 @@ describe Yaoc::Strategies::ToHashMapping do
4
4
  subject{
5
5
  Struct.new(:to_convert) do
6
6
  include Yaoc::MappingBase
7
- include Yaoc::Strategies::ToHashMapping
7
+ self.mapping_strategy = Yaoc::Strategies::ToHashMapping
8
8
  end
9
9
  }
10
10
 
@@ -20,7 +20,7 @@ describe Yaoc::Strategies::ToHashMapping do
20
20
  {id: 1, name: "paul"}
21
21
  }
22
22
 
23
- describe ".call" do
23
+ describe "#call" do
24
24
 
25
25
  it "creates a hash from a object" do
26
26
  subject.map(:id, :id)
@@ -41,7 +41,7 @@ describe Yaoc::Strategies::ToHashMapping do
41
41
 
42
42
  it "uses my converter proc" do
43
43
  subject.map(:id, :id)
44
- subject.map(:name, :fullname, ->(source, result){ result.merge({name: source.fetch(:name) + " Hello World"}) })
44
+ subject.map(:name, :fullname, ->(source, result){ fill_result_with_value(result, :name, source.fetch(:name) + " Hello World") })
45
45
 
46
46
  ext_expectation = expected_hash.clone
47
47
  ext_expectation[:name] += " Hello World"
data/yaoc.gemspec CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
7
7
  spec.name = "yaoc"
8
8
  spec.version = Yaoc::VERSION
9
9
  spec.authors = ["Dieter Späth"]
10
- spec.email = ["dieter.spaeth@gmx.de"]
10
+ spec.email = ["shad0wrunner@gmx.de"]
11
11
  spec.summary = %q{Yet another object converter}
12
12
  spec.description = %q{Yet another object converter}
13
13
  spec.homepage = "https://github.com/slowjack2k/yaoc"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yaoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dieter Späth
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-23 00:00:00.000000000 Z
11
+ date: 2014-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: abstract_type
@@ -208,7 +208,7 @@ dependencies:
208
208
  version: '0'
209
209
  description: Yet another object converter
210
210
  email:
211
- - dieter.spaeth@gmx.de
211
+ - shad0wrunner@gmx.de
212
212
  executables: []
213
213
  extensions: []
214
214
  extra_rdoc_files: []
@@ -222,16 +222,20 @@ files:
222
222
  - lib/yaoc.rb
223
223
  - lib/yaoc/converter_builder.rb
224
224
  - lib/yaoc/mapping_base.rb
225
+ - lib/yaoc/mapping_to_class.rb
225
226
  - lib/yaoc/object_mapper.rb
226
227
  - lib/yaoc/strategies/to_array_mapping.rb
227
228
  - lib/yaoc/strategies/to_hash_mapping.rb
228
229
  - lib/yaoc/version.rb
229
230
  - spec/acceptance/map_objects_spec.rb
231
+ - spec/acceptance/map_to_objects_using_other_converters_spec.rb
230
232
  - spec/acceptance/map_to_objects_with_positional_constructors_spec.rb
233
+ - spec/integration/lib/yaoc/converter_builder_spec.rb
231
234
  - spec/spec_helper.rb
232
235
  - spec/support/feature.rb
233
236
  - spec/unit/lib/yaoc/converter_builder_spec.rb
234
237
  - spec/unit/lib/yaoc/mapping_base_spec.rb
238
+ - spec/unit/lib/yaoc/mapping_to_class_spec.rb
235
239
  - spec/unit/lib/yaoc/object_mapper_spec.rb
236
240
  - spec/unit/lib/yaoc/strategies/to_array_mapping_spec.rb
237
241
  - spec/unit/lib/yaoc/strategies/to_hash_mapping_spec.rb
@@ -262,11 +266,14 @@ specification_version: 4
262
266
  summary: Yet another object converter
263
267
  test_files:
264
268
  - spec/acceptance/map_objects_spec.rb
269
+ - spec/acceptance/map_to_objects_using_other_converters_spec.rb
265
270
  - spec/acceptance/map_to_objects_with_positional_constructors_spec.rb
271
+ - spec/integration/lib/yaoc/converter_builder_spec.rb
266
272
  - spec/spec_helper.rb
267
273
  - spec/support/feature.rb
268
274
  - spec/unit/lib/yaoc/converter_builder_spec.rb
269
275
  - spec/unit/lib/yaoc/mapping_base_spec.rb
276
+ - spec/unit/lib/yaoc/mapping_to_class_spec.rb
270
277
  - spec/unit/lib/yaoc/object_mapper_spec.rb
271
278
  - spec/unit/lib/yaoc/strategies/to_array_mapping_spec.rb
272
279
  - spec/unit/lib/yaoc/strategies/to_hash_mapping_spec.rb