yaoc 0.0.6 → 0.0.7

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: 12e7c498b11d4f4f205c85146f98f715d49d9f52
4
- data.tar.gz: aba743b04f8bb624c80758aa6f4466ad467ae4d9
3
+ metadata.gz: 115be6510d49cc1ed39509369d8a13b35574afff
4
+ data.tar.gz: 77bc38e239f5ee0dad8a86e4e4e22fa6fa294c46
5
5
  SHA512:
6
- metadata.gz: 05c3efaa5c1e2862b10194039dbaca983dfdd366fab365aab1a1aa93551265aa286f68387979d69f939409dec3c21bb28f79a876a851855979116afb8d4dfd22
7
- data.tar.gz: b4919d5988c9b6cc7c9e36a082e5fe8b2c9eaf712157533a85736c7bf9a081a4a90b90caaa6239b56d62612f6654af67dc67dfaa5c3d6ea3e6b7924492ef03ef
6
+ metadata.gz: 49986fe1421711286cbc6e67ac58285fb625ad143e5f00bd280807a900884936d43b62fe7e5921cfb40f01603f1393c1c9eefc654b4b5fdd142c3f8b5db3f2b3
7
+ data.tar.gz: 41ccc8c0e963f2839e7f610fe313b371e8199fdd9ac521a132ae01bbe6a5ff50336148b4bdb158e3e74d271031f89a2a7db640c93b451d1e318ec4ffd3c8e2ec
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Yaoc [![Code Climate](https://codeclimate.com/github/slowjack2k/yaoc.png)](https://codeclimate.com/github/slowjack2k/yaoc) [![Build Status](https://travis-ci.org/slowjack2k/yaoc.png?branch=master)](https://travis-ci.org/slowjack2k/yaoc) [![Coverage Status](https://coveralls.io/repos/slowjack2k/yaoc/badge.png?branch=master)](https://coveralls.io/r/slowjack2k/yaoc?branch=master) [![Gem Version](https://badge.fury.io/rb/yaoc.png)](http://badge.fury.io/rb/yaoc)
2
2
 
3
- Indentation of this gem is to learn and train a little ruby.
3
+ Converting one ruby object into another with some rules.
4
4
 
5
5
  ## Installation
6
6
 
@@ -307,6 +307,57 @@ puts new_user5
307
307
 
308
308
  ```
309
309
 
310
+ ### How can I lazy load some expensive to convert attributes?
311
+
312
+ ```ruby
313
+ require 'yaoc'
314
+
315
+ include Yaoc::Helper
316
+
317
+ puts "\n" * 5
318
+
319
+
320
+ OldUser6 = StructHE(:id) do
321
+
322
+ def names=(new_names)
323
+ @names = new_names
324
+ end
325
+
326
+ def names
327
+ puts 'some expensive operation in progress ...'
328
+ sleep 10
329
+ @names
330
+ end
331
+
332
+ end
333
+ User6 = StructHE(:id, :names)
334
+
335
+
336
+ user_mapper = Yaoc::ObjectMapper.new(User6, OldUser6).tap do |mapper|
337
+ mapper.add_mapping do
338
+ fetcher :public_send
339
+ rule to: [:id, :names],
340
+ lazy_loading: [false, true]
341
+ end
342
+ end
343
+
344
+ old_user6 = OldUser6.new(id: 'my_id_1', names: ['one', 'two', 'three', 'four'])
345
+ new_user6 = user_mapper.load(old_user6)
346
+
347
+ puts new_user6.id.inspect
348
+ puts new_user6.names.inspect
349
+ puts new_user6
350
+
351
+
352
+ puts "\n" * 5
353
+
354
+ # "my_id_1"
355
+ # some expensive operation in progress ...
356
+ # ["one", "two", "three", "four"]
357
+ #<struct User6 id="my_id_1", names=["one", "two", "three", "four"]>
358
+
359
+ ```
360
+
310
361
  ## Contributing
311
362
 
312
363
  1. Fork it ( http://github.com/slowjack2k/yaoc/fork )
data/Rakefile CHANGED
@@ -8,6 +8,6 @@ task :test => :spec
8
8
 
9
9
  desc "Run RSpec with code coverage"
10
10
  task :coverage do
11
- ENV['COVERAGE'] = "true"
11
+ ENV['SIMPLE_COVERAGE'] = "true"
12
12
  Rake::Task["spec"].execute
13
13
  end
@@ -0,0 +1,47 @@
1
+ require 'bundler/setup'
2
+ Bundler.require(:development)
3
+
4
+ require 'yaoc'
5
+
6
+ include Yaoc::Helper
7
+
8
+ puts "\n" * 5
9
+
10
+
11
+ OldUser6 = StructHE(:id) do
12
+
13
+ def names=(new_names)
14
+ @names = new_names
15
+ end
16
+
17
+ def names
18
+ puts 'some expensive operation in progress ...'
19
+ sleep 10
20
+ @names
21
+ end
22
+
23
+ end
24
+ User6 = StructHE(:id, :names)
25
+
26
+
27
+ user_mapper = Yaoc::ObjectMapper.new(User6, OldUser6).tap do |mapper|
28
+ mapper.add_mapping do
29
+ fetcher :public_send
30
+ rule to: [:id, :names],
31
+ lazy_loading: [false, true]
32
+ end
33
+ end
34
+
35
+ old_user6 = OldUser6.new(id: 'my_id_1', names: ['one', 'two', 'three', 'four'])
36
+ new_user6 = user_mapper.load(old_user6)
37
+
38
+ puts new_user6.id.inspect
39
+ puts new_user6.names.inspect
40
+ puts new_user6
41
+
42
+
43
+ puts "\n" * 5
44
+
45
+
46
+
47
+
@@ -0,0 +1,7 @@
1
+ Dir[File.join(File.expand_path(__dir__ ), "*.rb")].sort.each do |f|
2
+ unless f =~ /#{__FILE__}$/
3
+ command = %W(ruby #{f})
4
+ puts "executing #{command.join(" ")}"
5
+ system *command
6
+ end
7
+ end
@@ -1,5 +1,4 @@
1
1
  require "yaoc/version"
2
- require 'abstract_type'
3
2
  require 'yaoc/mapping_base'
4
3
  require 'yaoc/mapping_to_class'
5
4
 
@@ -1,22 +1,28 @@
1
1
  module Yaoc
2
2
 
3
3
  class NormalizedParameters
4
- attr_accessor :to_s, :from_s, :converter_s
4
+ attr_accessor :to_s, :from_s, :converter_s, :lazy_loading_s
5
5
 
6
- def initialize(to, from, converter, object_converter, is_collection)
6
+ def initialize(to, from, converter, object_converter, is_collection, lazy_loading)
7
7
  self.to_s = Array(to)
8
8
  self.from_s = Array(from)
9
9
  self.converter_s = Array(converter)
10
+ self.lazy_loading_s = Array(lazy_loading)
10
11
 
11
12
  object_converter_s = Array(object_converter)
12
13
  is_collection_s = Array(is_collection)
13
14
 
14
15
  self.to_s.each_with_index do |to, index|
15
16
  from_s[index] ||= to
17
+ lazy_loading_s[index] ||= false
16
18
  end
17
19
 
18
20
  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])
21
+ converter_s[index] = converter_to_proc(to_s[index],
22
+ from_s[index],
23
+ object_converter,
24
+ !!is_collection_s[index],
25
+ !!lazy_loading_s[index])
20
26
  end
21
27
 
22
28
  end
@@ -25,30 +31,64 @@ module Yaoc
25
31
  return to_enum(__callee__) unless block_given?
26
32
 
27
33
  self.to_s.each_with_index do |to, index|
28
- yield to, from_s[index] , converter_s[index]
34
+ yield to, from_s[index] , converter_s[index], lazy_loading_s[index]
29
35
  end
30
36
  end
31
37
 
32
- def converter_to_proc(to, from, converter, is_collection)
38
+ def converter_to_proc(to, from, converter, is_collection, deferred)
33
39
  ->(source, result){
34
- object_to_convert = source.public_send(fetcher, from)
35
- converted_object = nil
40
+ get_value_with = ->{
41
+ object_to_convert = source.public_send(fetcher, from)
42
+
43
+ if is_collection
44
+ object_to_convert.map(&converter)
45
+ else
46
+ converter_as_proc = converter.to_proc
47
+ converter_as_proc.call(object_to_convert)
48
+ end
49
+ }
50
+
51
+ fill_result_from_proc(result, to, get_value_with, deferred)
52
+ }
53
+ end
36
54
 
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
55
+ end
43
56
 
44
- fill_result_with_value(result, to, converted_object)
45
- }
57
+ module BuilderDSLMethods
58
+ def add_mapping(&block)
59
+ instance_eval &block
60
+ apply_commands!
46
61
  end
47
62
 
63
+ def rule(to: nil, from: to, converter: nil, object_converter: nil, is_collection: nil, lazy_loading: nil)
64
+ self.all_commands_applied = false
65
+
66
+ NormalizedParameters.new(to, from, converter, object_converter, is_collection, lazy_loading).each do |to, from, converter, lazy_loading|
67
+ build_commands.push ->{ converter_class.map(to: to, from: from , converter: converter, lazy_loading: lazy_loading) }
68
+ end
69
+ end
70
+
71
+ def fetch_with(new_fetcher)
72
+ self.fetcher = new_fetcher
73
+ end
74
+
75
+ def with_strategy(new_strategy)
76
+ self.strategy = new_strategy
77
+ end
78
+
79
+ def build_commands_ordered
80
+ if command_order == :recorded_order
81
+ build_commands
82
+ else
83
+ build_commands.reverse
84
+ end
85
+ end
48
86
  end
49
87
 
50
88
 
51
89
  class ConverterBuilder
90
+ include BuilderDSLMethods
91
+
52
92
  attr_accessor :build_commands, :command_order,
53
93
  :strategy, :all_commands_applied
54
94
 
@@ -60,19 +100,6 @@ module Yaoc
60
100
  self.all_commands_applied = false
61
101
  end
62
102
 
63
- def add_mapping(&block)
64
- instance_eval &block
65
- apply_commands!
66
- end
67
-
68
- def rule(to: nil, from: to, converter: nil, object_converter: nil, is_collection: nil)
69
- self.all_commands_applied = false
70
-
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) }
73
- end
74
- end
75
-
76
103
  def apply_commands!
77
104
  reset_converters!
78
105
  self.all_commands_applied = true
@@ -120,22 +147,6 @@ module Yaoc
120
147
  @fetcher ||= :fetch
121
148
  end
122
149
 
123
- def fetch_with(new_fetcher)
124
- self.fetcher = new_fetcher
125
- end
126
-
127
- def with_strategy(new_strategy)
128
- self.strategy = new_strategy
129
- end
130
-
131
- def build_commands_ordered
132
- if command_order == :recorded_order
133
- build_commands
134
- else
135
- build_commands.reverse
136
- end
137
- end
138
-
139
150
  def reset_converters!
140
151
  @converter_class = nil
141
152
  end
@@ -0,0 +1,33 @@
1
+ module Yaoc
2
+ module Helper
3
+ class ToProcDelegator < SimpleDelegator
4
+ attr_accessor :_initialisation_proc, :_initialisation_proc_loaded
5
+
6
+ def initialize(_initialisation_proc)
7
+ super(nil).tap do
8
+ self._initialisation_proc = _initialisation_proc
9
+ self._initialisation_proc_loaded = false
10
+ end
11
+ end
12
+
13
+
14
+ def __getobj__
15
+ unless self._initialisation_proc_loaded
16
+ self._initialisation_proc_loaded = true
17
+ __setobj__(self._initialisation_proc.call())
18
+ end
19
+
20
+ super
21
+ end
22
+
23
+ def class
24
+ __getobj__.class
25
+ end
26
+
27
+ def kind_of?(some_class)
28
+ super || __getobj__.kind_of?(some_class)
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -1,6 +1,5 @@
1
1
  module Yaoc
2
2
  module MappingBase
3
- include AbstractType
4
3
 
5
4
  def self.included(other)
6
5
  other.extend(ClassMethods)
@@ -19,13 +18,31 @@ module Yaoc
19
18
  end
20
19
 
21
20
  def call
22
- self.class.mapping_strategy.call(self)
21
+ unless to_convert.nil?
22
+ self.class.mapping_strategy.call(self)
23
+ else
24
+ nil
25
+ end
23
26
  end
24
27
 
25
28
  def fill_result_with_value(result, key, value)
26
29
  result.tap{|taped_result| taped_result[key] = value}
27
30
  end
28
31
 
32
+ def fill_result_from_proc(result, key, proc, deferred=false)
33
+ value = if deferred
34
+ deferrer_strategy(proc)
35
+ else
36
+ proc.call
37
+ end
38
+
39
+ fill_result_with_value(result, key, value)
40
+ end
41
+
42
+ def deferrer_strategy(proc)
43
+ Yaoc::Helper::ToProcDelegator.new(proc)
44
+ end
45
+
29
46
 
30
47
  def converter_methods
31
48
  self.class.converter_methods
@@ -36,11 +53,14 @@ module Yaoc
36
53
  end
37
54
 
38
55
  module ClassMethods
39
- include AbstractType
40
56
 
41
- def converter_proc(to, from)
57
+ def converter_proc(to, from, deferred=false)
42
58
  -> (to_convert, result){
43
- fill_result_with_value(result, to, to_convert.public_send(fetcher, from))
59
+ get_value_with = ->{
60
+ to_convert.public_send(fetcher, from)
61
+ }
62
+
63
+ fill_result_from_proc(result, to, get_value_with, deferred)
44
64
  }
45
65
  end
46
66
 
@@ -52,9 +72,11 @@ module Yaoc
52
72
  @mapping_strategy
53
73
  end
54
74
 
55
- def map(to, from, block=nil)
75
+ def map(to: nil, from: to, converter: nil, lazy_loading: false)
56
76
  class_private_module(:Mapping).tap do |mod|
57
- mod.send :define_method, "map_#{"%04d" %[converter_methods.count]}_#{from}_to_#{to}".to_sym, (block || converter_proc(to, from))
77
+ method_implementation = converter || converter_proc(to, from, lazy_loading)
78
+
79
+ mod.send :define_method, "map_#{"%04d" %[converter_methods.count]}_#{from}_to_#{to}".to_sym, method_implementation
58
80
  include mod
59
81
  end
60
82
  end
@@ -9,10 +9,14 @@ module Yaoc
9
9
  module InstanceMethods
10
10
  def call(pre_created_object=nil)
11
11
  source_converted_to_hash_or_array = super()
12
- if pre_created_object.nil?
13
- create_target_from_class(source_converted_to_hash_or_array)
12
+ unless source_converted_to_hash_or_array.nil?
13
+ if pre_created_object.nil?
14
+ create_target_from_class(source_converted_to_hash_or_array)
15
+ else
16
+ fill_target_object(source_converted_to_hash_or_array, pre_created_object)
17
+ end
14
18
  else
15
- fill_target_object(source_converted_to_hash_or_array, pre_created_object)
19
+ nil
16
20
  end
17
21
  end
18
22
 
@@ -1,47 +1,18 @@
1
1
  module Yaoc
2
2
 
3
- class ObjectMapper
4
- attr_accessor :load_result_source, :dump_result_source
5
-
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
- end
10
-
11
- def load(fetch_able, object_to_fill=nil)
12
- converter(fetch_able).call(object_to_fill)
13
- end
14
-
15
- def dump(object, object_to_fill=nil)
16
- reverse_converter(object).call(object_to_fill)
17
- end
18
-
3
+ module MapperDSLMethods
19
4
  def add_mapping(&block)
20
5
  instance_eval &block
21
- apply_commands
22
- end
23
-
24
- def converter(fetch_able=nil)
25
- converter_builder.converter(fetch_able, load_result_source)
26
- end
27
-
28
- def reverse_converter(fetch_able=nil)
29
- reverse_converter_builder.converter(fetch_able, dump_result_source)
30
- end
31
-
32
- protected
33
-
34
- def apply_commands
35
- converter_builder.apply_commands!
36
- reverse_converter_builder.apply_commands!
6
+ apply_commands!
37
7
  end
38
8
 
39
9
  def rule(to: nil, from: to, converter: nil,
40
- reverse_to: from,
41
- reverse_from: to,
42
- reverse_converter: nil,
43
- object_converter: nil,
44
- is_collection: nil)
10
+ reverse_to: from,
11
+ reverse_from: to,
12
+ reverse_converter: nil,
13
+ object_converter: nil,
14
+ is_collection: nil,
15
+ lazy_loading: nil)
45
16
 
46
17
  object_converter = Array(object_converter)
47
18
 
@@ -51,6 +22,7 @@ module Yaoc
51
22
  converter: converter,
52
23
  object_converter: object_converter.map(&:converter),
53
24
  is_collection: is_collection,
25
+ lazy_loading: lazy_loading
54
26
  )
55
27
 
56
28
  reverse_converter_builder.rule(
@@ -59,6 +31,7 @@ module Yaoc
59
31
  converter: reverse_converter,
60
32
  object_converter: object_converter.map(&:reverse_converter),
61
33
  is_collection: is_collection,
34
+ lazy_loading: lazy_loading
62
35
  )
63
36
  end
64
37
 
@@ -77,6 +50,40 @@ module Yaoc
77
50
  def reverse_strategy(new_strategy)
78
51
  reverse_converter_builder.strategy = new_strategy
79
52
  end
53
+ end
54
+
55
+ class ObjectMapper
56
+ include MapperDSLMethods
57
+
58
+ attr_accessor :load_result_source, :dump_result_source
59
+
60
+ def initialize(load_result_source, dump_result_source=nil)
61
+ self.load_result_source = load_result_source
62
+ self.dump_result_source = dump_result_source
63
+ end
64
+
65
+ def load(fetch_able, object_to_fill=nil)
66
+ converter(fetch_able).call(object_to_fill)
67
+ end
68
+
69
+ def dump(object, object_to_fill=nil)
70
+ reverse_converter(object).call(object_to_fill)
71
+ end
72
+
73
+ def converter(fetch_able=nil)
74
+ converter_builder.converter(fetch_able, load_result_source)
75
+ end
76
+
77
+ def reverse_converter(fetch_able=nil)
78
+ reverse_converter_builder.converter(fetch_able, dump_result_source)
79
+ end
80
+
81
+ protected
82
+
83
+ def apply_commands!
84
+ converter_builder.apply_commands!
85
+ reverse_converter_builder.apply_commands!
86
+ end
80
87
 
81
88
  def converter_builder
82
89
  @converter_builder ||= Yaoc::ConverterBuilder.new()
@@ -1,3 +1,3 @@
1
1
  module Yaoc
2
- VERSION = "0.0.6"
2
+ VERSION = "0.0.7"
3
3
  end
@@ -0,0 +1,59 @@
1
+ require "spec_helper"
2
+
3
+ feature "Map objects to classes with lazy loading", %q{
4
+ In order to defer object mapping
5
+ as a lib user
6
+ I want to map object from an input object to an output object with lazy loading support
7
+ } do
8
+
9
+ given(:mapper){
10
+ Yaoc::ObjectMapper.new(new_user_class, old_user_class).tap do |mapper|
11
+ mapper.add_mapping do
12
+ fetcher :public_send
13
+ rule to: [:id, :names],
14
+ lazy_loading: [false, true]
15
+ end
16
+ end
17
+ }
18
+
19
+ given(:new_user_class){
20
+ Yaoc::Helper::StructHE(:id, :names)
21
+ }
22
+
23
+ given(:old_user_class){
24
+ Yaoc::Helper::StructHE(:id, :names)
25
+ }
26
+
27
+ given(:existing_old_user){
28
+ old_user_class.new(
29
+ id: 'existing_user_2',
30
+ names: ['first_name', 'second_name']
31
+ )
32
+ }
33
+
34
+ given(:existing_user){
35
+ new_user_class.new(
36
+ id: 'existing_user_2',
37
+ names: ['first_name', 'second_name']
38
+ )
39
+ }
40
+
41
+ scenario "creates an result object from an input_object deferred" do
42
+ converted_user = mapper.load(existing_old_user)
43
+ new_names = ["new_name1", "new_name2"]
44
+
45
+ existing_old_user.names = new_names # show defer through changes after loading an object
46
+
47
+ expect(converted_user.names).to eq new_names
48
+ end
49
+
50
+ scenario "dumps an result object as source object defered" do
51
+ converted_user = mapper.dump(existing_user)
52
+ new_names = ["new_name1", "new_name2"]
53
+
54
+ existing_user.names = new_names # show defer through changes after loading an object
55
+
56
+ expect(converted_user.names).to eq new_names
57
+ end
58
+
59
+ end
@@ -1,18 +1,17 @@
1
1
  require 'bundler/setup'
2
2
  Bundler.require(:development)
3
3
 
4
+ require 'coveralls'
5
+ Coveralls.wear! unless ENV["SIMPLE_COVERAGE"]
4
6
 
5
7
  begin
6
- if ENV["COVERAGE"]
8
+ if ENV["SIMPLE_COVERAGE"]
7
9
  require 'simplecov'
8
10
  SimpleCov.start do
9
11
  add_group "Lib", "lib"
10
12
 
11
13
  add_filter "/spec/"
12
14
  end
13
- else
14
- require 'coveralls'
15
- Coveralls.wear!
16
15
  end
17
16
  rescue LoadError
18
17
  warn "=" * 80
@@ -16,13 +16,27 @@ describe Yaoc::ConverterBuilder do
16
16
  double("converter", call: nil)
17
17
  }
18
18
 
19
+ let(:default_map_args){
20
+ {
21
+ to: :id,
22
+ from: :id,
23
+ converter: nil,
24
+ lazy_loading: false
25
+ }
26
+ }
27
+
19
28
  describe "#command_order" do
20
29
 
21
30
  it "applies command in recorded order as default" do
22
31
  subject.command_order = :recorded_order
23
32
 
24
- expect(converter_class).to receive(:map).ordered.with(:id, :id, nil)
25
- expect(converter_class).to receive(:map).ordered.with(:name, :name, nil)
33
+ expected_args_first = default_map_args.clone
34
+ expected_args_second = default_map_args.clone
35
+
36
+ expected_args_second[:to] = expected_args_second[:from] = :name
37
+
38
+ expect(converter_class).to receive(:map).ordered.with(expected_args_first)
39
+ expect(converter_class).to receive(:map).ordered.with(expected_args_second)
26
40
 
27
41
  subject.add_mapping do
28
42
  rule to: :id
@@ -34,8 +48,11 @@ describe Yaoc::ConverterBuilder do
34
48
  it "applies command in reverse recorded order when wanted" do
35
49
  subject.command_order = :reverse_order
36
50
 
37
- expect(converter_class).to receive(:map).ordered.with(:name, :name, nil)
38
- expect(converter_class).to receive(:map).ordered.with(:id, :id, nil)
51
+ expected_args_first = default_map_args.clone.merge({to: :name, from: :name})
52
+ expected_args_second = default_map_args.clone
53
+
54
+ expect(converter_class).to receive(:map).ordered.with(expected_args_first)
55
+ expect(converter_class).to receive(:map).ordered.with(expected_args_second)
39
56
 
40
57
  subject.add_mapping do
41
58
  rule to: :id
@@ -64,8 +81,7 @@ describe Yaoc::ConverterBuilder do
64
81
 
65
82
  describe "#rule" do
66
83
  it "creates a converter" do
67
-
68
- expect(converter_class).to receive(:map).with(:id, :id2, :some_proc)
84
+ expect(converter_class).to receive(:map).with(to: :id, from: :id2, converter: :some_proc, lazy_loading: false)
69
85
 
70
86
  subject.add_mapping do
71
87
  rule to: :id,
@@ -76,7 +92,7 @@ describe Yaoc::ConverterBuilder do
76
92
  end
77
93
 
78
94
  it "uses defaults" do
79
- expect(converter_class).to receive(:map).with(:id, :id, nil)
95
+ expect(converter_class).to receive(:map).with(default_map_args)
80
96
 
81
97
  subject.add_mapping do
82
98
  rule to: :id
@@ -85,8 +101,11 @@ describe Yaoc::ConverterBuilder do
85
101
  end
86
102
 
87
103
  it "allows to use array of attributes" do
88
- expect(converter_class).to receive(:map).ordered.with(:id, :id, nil)
89
- expect(converter_class).to receive(:map).ordered.with(:name, :name, nil)
104
+ expected_args_first = default_map_args.clone
105
+ expected_args_second = default_map_args.clone.merge({to: :name, from: :name})
106
+
107
+ expect(converter_class).to receive(:map).ordered.with(expected_args_first)
108
+ expect(converter_class).to receive(:map).ordered.with(expected_args_second)
90
109
 
91
110
  subject.add_mapping do
92
111
  rule to: [:id, :name]
@@ -94,8 +113,12 @@ describe Yaoc::ConverterBuilder do
94
113
  end
95
114
 
96
115
  it "use the right 'to' when 'from' in arrays is missing" do
97
- expect(converter_class).to receive(:map).ordered.with(:id, :r_id, nil)
98
- expect(converter_class).to receive(:map).ordered.with(:name, :name, nil)
116
+ expected_args_first = default_map_args.clone.merge({from: :r_id})
117
+ expected_args_second = default_map_args.clone.merge({to: :name, from: :name})
118
+
119
+
120
+ expect(converter_class).to receive(:map).ordered.with(expected_args_first)
121
+ expect(converter_class).to receive(:map).ordered.with(expected_args_second)
99
122
 
100
123
  subject.add_mapping do
101
124
  rule to: [:id, :name],
@@ -104,7 +127,7 @@ describe Yaoc::ConverterBuilder do
104
127
  end
105
128
 
106
129
  it "supports the use of a object converter" do
107
- expect(converter_class).to receive(:map).ordered.with(:id, :id, kind_of(Proc))
130
+ expect(converter_class).to receive(:map).ordered.with(to: :id, from: :id, converter: kind_of(Proc), lazy_loading: false)
108
131
  other_converter = :some_converter
109
132
 
110
133
  subject.add_mapping do
@@ -115,7 +138,9 @@ describe Yaoc::ConverterBuilder do
115
138
  end
116
139
 
117
140
  it "supports the collection flag for object converters" do
118
- expect(converter_class).to receive(:map).ordered.with(:id, :id, kind_of(Proc))
141
+ expected_args = default_map_args.clone.merge({converter: kind_of(Proc)})
142
+
143
+ expect(converter_class).to receive(:map).ordered.with(expected_args)
119
144
  other_converter = :some_converter
120
145
 
121
146
  subject.add_mapping do
@@ -125,6 +150,17 @@ describe Yaoc::ConverterBuilder do
125
150
  end
126
151
 
127
152
  end
153
+
154
+ it "supports lazy loading" do
155
+ expected_args = default_map_args.clone.merge({lazy_loading: true})
156
+
157
+ expect(converter_class).to receive(:map).ordered.with(expected_args)
158
+
159
+ subject.add_mapping do
160
+ rule to: :id,
161
+ lazy_loading: true
162
+ end
163
+ end
128
164
  end
129
165
 
130
166
  describe "#converter" do
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe Yaoc::Helper::ToProcDelegator do
4
+ subject{
5
+ Yaoc::Helper::ToProcDelegator.new(lazy_proc)
6
+ }
7
+
8
+ let(:lazy_proc){
9
+ ->{
10
+ [:some_value]
11
+ }
12
+ }
13
+
14
+ it 'evaluates a proc not with initialisation' do
15
+ expect(lazy_proc).not_to receive :call
16
+ Yaoc::Helper::ToProcDelegator.new(lazy_proc)
17
+ end
18
+
19
+ it 'evaluates a proc when methods are delegated' do
20
+ expect(lazy_proc).to receive(:call)
21
+ subject.respond_to? :some_method_name
22
+ end
23
+
24
+ it 'delegates to the proc result' do
25
+ expect(subject.first).to eq :some_value
26
+ end
27
+
28
+ describe 'kind_of?' do
29
+
30
+ it 'returns true when class is "real class"' do
31
+ expect(subject).to be_kind_of Yaoc::Helper::ToProcDelegator
32
+ end
33
+
34
+ it 'returns true when class is delegated class' do
35
+ expect(subject).to be_kind_of lazy_proc.call.class
36
+ end
37
+
38
+ it 'returns false for other classes' do
39
+ expect(subject).not_to be_kind_of String
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -17,7 +17,7 @@ describe Yaoc::MappingBase do
17
17
 
18
18
  describe "created module" do
19
19
  it "can be inspected" do
20
- subject.map(:foo, :bar)
20
+ subject.map(to: :foo, from: :bar)
21
21
  expect(subject.class_private_module.inspect).to include("map_0000_bar_to_foo")
22
22
  end
23
23
  end
@@ -25,24 +25,44 @@ describe Yaoc::MappingBase do
25
25
  describe ".map" do
26
26
 
27
27
  it "creates a bunch of mapping methods" do
28
- subject.map(:foo, :bar)
29
- subject.map(:bar, :foo)
28
+ subject.map(to: :foo, from: :bar)
29
+ subject.map(to: :bar, from: :foo)
30
30
 
31
31
  expect(subject.new({bar: :my_to_convert, foo: :my_result}).call()).to eq [{:foo=>:my_to_convert, :bar=>:my_result},
32
32
  {:foo=>:my_to_convert, :bar=>:my_result}]
33
33
  end
34
34
 
35
35
  it "uses my converter when provided" do
36
- subject.map(:bar, :foo, ->(*){})
36
+ subject.map(to: :bar, from: :foo, converter: ->(*){})
37
37
 
38
38
  expect(subject.new(:my_to_convert).call()).to eq [nil]
39
39
  end
40
+
41
+ it 'supports deferred mappings' do
42
+ subject.map(to: :bar, from: :foo, lazy_loading: true)
43
+ object_to_convert = {foo: [:my_result]}
44
+
45
+ expect(object_to_convert).not_to receive :fetch
46
+
47
+ subject.new(object_to_convert).call()
48
+ end
49
+
50
+ it "returns results for deferred mappings" do
51
+ subject.map(to: :bar, from: :foo, lazy_loading: true)
52
+ object_to_convert = double("object_to_convert")
53
+
54
+ result = subject.new(object_to_convert).call()
55
+
56
+ expect(object_to_convert).to receive(:fetch).with(:foo).and_return([:my_result])
57
+
58
+ expect(result.first[:bar].first).to eq :my_result
59
+ end
40
60
  end
41
61
 
42
62
  describe "#converter_methods" do
43
63
  it "preserves method order" do
44
- subject.map(0, 1, ->(*){})
45
- subject.map(1, :a, ->(*){})
64
+ subject.map(to: 0, from: 1, converter: ->(*){})
65
+ subject.map(to: 1, from: :a, converter: ->(*){})
46
66
 
47
67
  expect(subject.converter_methods).to eq [:map_0000_1_to_0, :map_0001_a_to_1]
48
68
  end
@@ -71,13 +91,21 @@ describe Yaoc::MappingBase do
71
91
  end
72
92
 
73
93
  describe "#call" do
74
- it "delegates execution to strategy" do
75
- mapper = subject.new()
94
+ let(:mapper){
95
+ subject.new(:some_thing)
96
+ }
76
97
 
98
+ it "delegates execution to strategy" do
77
99
  expect(subject.mapping_strategy).to receive(:call).with mapper
78
100
 
79
101
  mapper.call
80
102
  end
103
+
104
+ it "return nil when to_convert is nil" do
105
+ mapper.to_convert = nil
106
+ expect(mapper.call).to be_nil
107
+ end
108
+
81
109
  end
82
110
 
83
111
  describe "#to_proc" do
@@ -25,6 +25,10 @@ describe Yaoc::MappingToClass do
25
25
  {:name => :new_name}
26
26
  }
27
27
 
28
+ def to_convert
29
+ :some_thing
30
+ end
31
+
28
32
  end.new(expected_class)
29
33
  }
30
34
 
@@ -61,6 +65,11 @@ describe Yaoc::MappingToClass do
61
65
  expect(obj.name).to eq :new_name
62
66
  expect(obj.id).to eq :my_id
63
67
  end
68
+
69
+ it "returns nil when nothing to convert" do
70
+ subject.stub(to_convert: nil)
71
+ expect(subject.call).to be_nil
72
+ end
64
73
  end
65
74
 
66
75
  describe "#to_a" do
@@ -30,7 +30,8 @@ describe Yaoc::ObjectMapper do
30
30
  from: :id,
31
31
  converter: nil,
32
32
  object_converter: [],
33
- is_collection: nil
33
+ is_collection: nil,
34
+ lazy_loading: nil,
34
35
  }
35
36
  }
36
37
 
@@ -23,16 +23,16 @@ describe Yaoc::Strategies::ToArrayMapping do
23
23
  describe ".call" do
24
24
 
25
25
  it "creates a hash from a object" do
26
- subject.map(0, :id)
27
- subject.map(1, :name)
26
+ subject.map(to: 0, from: :id)
27
+ subject.map(to: 1, from: :name)
28
28
 
29
29
  expect(mapper.call).to eq(expected_array)
30
30
  end
31
31
 
32
32
 
33
33
  it "uses my converter proc" do
34
- subject.map(0, :id)
35
- subject.map(3, :fullname, ->(source, result){ fill_result_with_value(result, 3, "#{source.fetch(:name)} Hello World") })
34
+ subject.map(to: 0, from: :id)
35
+ subject.map(to: 3, from: :fullname, converter: ->(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"
@@ -48,8 +48,8 @@ describe Yaoc::Strategies::ToArrayMapping do
48
48
  }
49
49
 
50
50
  it "uses custom fetcher methods" do
51
- subject.map(0, :id)
52
- subject.map(1, :name)
51
+ subject.map(to: 0, from: :id)
52
+ subject.map(to: 1, from: :name)
53
53
 
54
54
  def mapper.fetcher
55
55
  :public_send
@@ -59,8 +59,8 @@ describe Yaoc::Strategies::ToArrayMapping do
59
59
  end
60
60
 
61
61
  it "works with arrays" do
62
- subject.map(1, 0)
63
- subject.map(0, 1)
62
+ subject.map(to: 1, from: 0)
63
+ subject.map(to: 0, from: 1)
64
64
 
65
65
  def mapper.fetcher
66
66
  :[]
@@ -23,15 +23,15 @@ describe Yaoc::Strategies::ToHashMapping do
23
23
  describe "#call" do
24
24
 
25
25
  it "creates a hash from a object" do
26
- subject.map(:id, :id)
27
- subject.map(:name, :name)
26
+ subject.map(to: :id, from: :id)
27
+ subject.map(to: :name, from: :name)
28
28
 
29
29
  expect(mapper.call).to eq(expected_hash)
30
30
  end
31
31
 
32
32
  it "renames attributes" do
33
- subject.map(:id, :id)
34
- subject.map(:fullname, :name)
33
+ subject.map(to: :id)
34
+ subject.map(to: :fullname, from: :name)
35
35
 
36
36
  renamed_expectation = expected_hash.clone
37
37
  renamed_expectation[:fullname] = renamed_expectation.delete :name
@@ -40,8 +40,8 @@ describe Yaoc::Strategies::ToHashMapping do
40
40
  end
41
41
 
42
42
  it "uses my converter proc" do
43
- subject.map(:id, :id)
44
- subject.map(:name, :fullname, ->(source, result){ fill_result_with_value(result, :name, source.fetch(:name) + " Hello World") })
43
+ subject.map(to: :id)
44
+ subject.map(to: :name, from: :fullname, converter: ->(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"
@@ -55,8 +55,8 @@ describe Yaoc::Strategies::ToHashMapping do
55
55
  }
56
56
 
57
57
  it "uses custom fetcher methods" do
58
- subject.map(:id, :id)
59
- subject.map(:name, :name)
58
+ subject.map(to: :id)
59
+ subject.map(to: :name)
60
60
 
61
61
  def mapper.fetcher
62
62
  :public_send
@@ -66,8 +66,8 @@ describe Yaoc::Strategies::ToHashMapping do
66
66
  end
67
67
 
68
68
  it "works with arrays" do
69
- subject.map(:id, 0)
70
- subject.map(:name, 1)
69
+ subject.map(to: :id, from: 0)
70
+ subject.map(to: :name, from: 1)
71
71
 
72
72
  def mapper.fetcher
73
73
  :[]
@@ -20,8 +20,6 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.required_ruby_version = '>= 2.0.0'
22
22
 
23
- spec.add_runtime_dependency "abstract_type", '~> 0.0.7'
24
-
25
23
  spec.add_development_dependency "bundler", "~> 1.5"
26
24
  spec.add_development_dependency "rake"
27
25
 
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yaoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
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-27 00:00:00.000000000 Z
11
+ date: 2014-01-28 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: abstract_type
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: 0.0.7
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: 0.0.7
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: bundler
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -225,9 +211,12 @@ files:
225
211
  - examples/03_positional_constructors.rb
226
212
  - examples/04_compositions.rb
227
213
  - examples/05_fill_existing_objects.rb
214
+ - examples/06_lazy_loading.rb
215
+ - examples/all_examples.rb
228
216
  - lib/yaoc.rb
229
217
  - lib/yaoc/converter_builder.rb
230
218
  - lib/yaoc/helper/struct_hash_constructor.rb
219
+ - lib/yaoc/helper/to_proc_delegator.rb
231
220
  - lib/yaoc/mapping_base.rb
232
221
  - lib/yaoc/mapping_to_class.rb
233
222
  - lib/yaoc/object_mapper.rb
@@ -237,12 +226,14 @@ files:
237
226
  - spec/acceptance/fill_existing_objects_spec.rb
238
227
  - spec/acceptance/map_objects_spec.rb
239
228
  - spec/acceptance/map_to_objects_using_other_converters_spec.rb
229
+ - spec/acceptance/map_to_objects_with_lazy_loading_spec.rb
240
230
  - spec/acceptance/map_to_objects_with_positional_constructors_spec.rb
241
231
  - spec/integration/lib/yaoc/converter_builder_spec.rb
242
232
  - spec/spec_helper.rb
243
233
  - spec/support/feature.rb
244
234
  - spec/unit/lib/yaoc/converter_builder_spec.rb
245
235
  - spec/unit/lib/yaoc/helper/struct_hash_constructor_spec.rb
236
+ - spec/unit/lib/yaoc/helper/to_proc_delegator_spec.rb
246
237
  - spec/unit/lib/yaoc/mapping_base_spec.rb
247
238
  - spec/unit/lib/yaoc/mapping_to_class_spec.rb
248
239
  - spec/unit/lib/yaoc/object_mapper_spec.rb
@@ -277,12 +268,14 @@ test_files:
277
268
  - spec/acceptance/fill_existing_objects_spec.rb
278
269
  - spec/acceptance/map_objects_spec.rb
279
270
  - spec/acceptance/map_to_objects_using_other_converters_spec.rb
271
+ - spec/acceptance/map_to_objects_with_lazy_loading_spec.rb
280
272
  - spec/acceptance/map_to_objects_with_positional_constructors_spec.rb
281
273
  - spec/integration/lib/yaoc/converter_builder_spec.rb
282
274
  - spec/spec_helper.rb
283
275
  - spec/support/feature.rb
284
276
  - spec/unit/lib/yaoc/converter_builder_spec.rb
285
277
  - spec/unit/lib/yaoc/helper/struct_hash_constructor_spec.rb
278
+ - spec/unit/lib/yaoc/helper/to_proc_delegator_spec.rb
286
279
  - spec/unit/lib/yaoc/mapping_base_spec.rb
287
280
  - spec/unit/lib/yaoc/mapping_to_class_spec.rb
288
281
  - spec/unit/lib/yaoc/object_mapper_spec.rb