yaoc 0.0.6 → 0.0.7

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