yaoc 0.0.4 → 0.0.5

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: 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