yaoc 0.0.3 → 0.0.4

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: 441263ba3b9fe09627de69b63629026703c7070d
4
- data.tar.gz: 48c6614551a01d37000e914bd48308aca9987424
3
+ metadata.gz: 409ba0cb455bbdea76b8dd9f32bd81c5d7d8a6bf
4
+ data.tar.gz: 37de097336722ccd09c26c44f943a6161355ae9f
5
5
  SHA512:
6
- metadata.gz: d6284f7e096825e82d6244e75eb239a1ef2d388bce4714c71d844619cbd0a71d8923770134947ee81e90a544c67255a9146ff463005794b28f53731f98cc772f
7
- data.tar.gz: cc8596b471a03029d0edf21f96dec0e47a1df2a5586ed496c331c9b260a7ea39af0aec3193d8d0d0e81f2a7dd658b3547398727b89c0b911c9155d5f86c304b4
6
+ metadata.gz: 1258d989f4d14f28c806c45daac46516d0277e471906583ad999d68a662b09deb792118fc9675a06b9df50c12ecfa558a1631d5c2226d26009d10c16d485c389
7
+ data.tar.gz: b3969999352325fe98045f0b2e5d3edd153f1b12915822a93a1b44f776893a2963cf943fed7103462c882b6a845df1c64f1e79404fabbee408dfc85e7956615a
data/.gitignore CHANGED
@@ -16,3 +16,4 @@ spec/reports
16
16
  test/tmp
17
17
  test/version_tmp
18
18
  tmp
19
+ coverage
data/Gemfile CHANGED
@@ -3,3 +3,5 @@ ruby "2.1.0"
3
3
 
4
4
  # Specify your gem's dependencies in yaoc.gemspec
5
5
  gemspec
6
+
7
+ gem 'simplecov', require: false, group: :test
data/README.md CHANGED
@@ -20,6 +20,8 @@ Or install it yourself as:
20
20
 
21
21
  Uptodate doc's look into the specs.
22
22
 
23
+ ### The resulting classes have hash enabled constructors?
24
+
23
25
  ```ruby
24
26
 
25
27
  require 'yaoc'
@@ -84,9 +86,12 @@ puts mapper.dump(new_user)
84
86
  #<struct User id=1, firstname="myfirst", lastname="mysecond", role="admin">
85
87
  #<struct OldUser id=1, fullname="no name", r_role="admin">
86
88
 
87
- # the resulting class has no hash enabled constructor?
88
89
 
89
- puts "\n" * 5
90
+ ```
91
+
92
+ ### The resulting classes have no hash enabled constructor?
93
+
94
+ ```ruby
90
95
 
91
96
  OldUser2 = Struct.new(:id, :fullname, :r_role)
92
97
 
@@ -144,9 +149,60 @@ puts mapper.dump(new_user2)
144
149
 
145
150
  ```
146
151
 
152
+ ### But my classes have positional constructor, what now?
153
+
154
+ ```ruby
155
+ OldUser3 = Struct.new(:id, :fullname, :r_role)
156
+ User3 = Struct.new(:id, :firstname, :lastname, :role)
157
+
158
+
159
+ mapper = Yaoc::ObjectMapper.new(User3, OldUser3).tap do |mapper|
160
+ mapper.add_mapping do
161
+ fetcher :public_send
162
+
163
+ strategy :to_array_mapping
164
+ reverse_strategy :to_array_mapping
165
+
166
+ rule to: 0, from: :id,
167
+ reverse_to: 0, reverse_from: :id
168
+
169
+ rule to: 1,
170
+ from: :fullname,
171
+
172
+ converter: ->(source, result){ result[1] = source.fullname.split().first },
173
+ reverse_converter: ->(source, result){ result[1] = "#{source.firstname} #{source.lastname}" }
174
+
175
+ rule to: 2,
176
+ from: :fullname,
177
+
178
+ converter: ->(source, result){ result[2] = source.fullname.split().last },
179
+ reverse_converter: ->(source, result){ result }
180
+
181
+ rule to: 3, from: :r_role,
182
+ reverse_to: 2, reverse_from: :role
183
+ end
184
+ end
185
+
186
+ old_user3 = OldUser3.new(1, "myfirst mysecond", "admin" )
187
+ new_user3 = mapper.load(old_user)
188
+
189
+ puts old_user3
190
+ puts new_user3
191
+
192
+ new_user3.firstname = "no"
193
+ new_user3.lastname = "name"
194
+
195
+ puts mapper.dump(new_user3)
196
+
197
+ #<struct OldUser3 id=1, fullname="myfirst mysecond", r_role="admin">
198
+ #<struct User3 id=1, firstname="myfirst", lastname="mysecond", role="admin">
199
+ #<struct OldUser3 id=1, fullname="no name", r_role="admin">
200
+
201
+ ```
202
+
147
203
  ## Contributing
148
204
 
149
- 1. Fork it ( http://github.com/<my-github-username>/yaoc/fork )
205
+ 1. Fork it ( http://github.com/slowjack2k/yaoc/fork )
150
206
  2. Create your feature branch (`git checkout -b my-new-feature`)
151
207
  3. Commit your changes (`git commit -am 'Add some feature'`)
152
208
  4. Push to the branch (`git push origin my-new-feature`)
data/Rakefile CHANGED
@@ -1 +1,13 @@
1
1
  require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new
5
+
6
+ task :default => :spec
7
+ task :test => :spec
8
+
9
+ desc "Run RSpec with code coverage"
10
+ task :coverage do
11
+ ENV['COVERAGE'] = "true"
12
+ Rake::Task["spec"].execute
13
+ end
@@ -1,12 +1,14 @@
1
1
  module Yaoc
2
2
 
3
3
  class ConverterBuilder
4
- attr_accessor :build_commands, :command_order
4
+ attr_accessor :build_commands, :command_order, :strategy, :all_commands_applied
5
5
 
6
6
  def initialize(command_order=:recorded_order, fetcher=:fetch)
7
7
  self.build_commands = []
8
8
  self.command_order = command_order
9
9
  self.fetcher = fetcher
10
+ self.strategy = :to_hash_mapping
11
+ self.all_commands_applied = false
10
12
  end
11
13
 
12
14
  def add_mapping(&block)
@@ -14,15 +16,9 @@ module Yaoc
14
16
  apply_commands!
15
17
  end
16
18
 
17
- def converter_class
18
- @converter_class ||= Struct.new(:to_convert, :fetcher) do
19
- include MappingBase
20
- include Strategies::ToHashMapping
21
- end
22
- end
23
-
24
-
25
19
  def rule(to: nil, from: to, converter: nil)
20
+ self.all_commands_applied = false
21
+
26
22
  to_s = Array(to)
27
23
  from_s = Array(from)
28
24
  converter_s = Array(converter)
@@ -34,11 +30,13 @@ module Yaoc
34
30
 
35
31
  def apply_commands!
36
32
  reset_converters!
33
+ self.all_commands_applied = true
37
34
 
38
35
  build_commands_ordered.each &:call
39
36
  end
40
37
 
41
38
  def converter(fetch_able)
39
+ raise "BuildCommandsNotExecuted" unless self.all_commands_applied?
42
40
  converter_class.new(fetch_able, fetcher)
43
41
  end
44
42
 
@@ -48,6 +46,30 @@ module Yaoc
48
46
 
49
47
  protected
50
48
 
49
+ def converter_class
50
+ @converter_class ||= Struct.new(:to_convert, :fetcher) do
51
+ include MappingBase
52
+ end.tap do |new_class|
53
+ new_class.send(:include, strategy_module)
54
+ end
55
+ end
56
+
57
+ def strategy_module
58
+ Yaoc::Strategies.const_get sym_as_module_name(strategy)
59
+ end
60
+
61
+ def sym_as_module_name(sym)
62
+ sym.to_s
63
+ .split("_")
64
+ .map(&:capitalize)
65
+ .join()
66
+ .to_sym
67
+ end
68
+
69
+ def all_commands_applied?
70
+ all_commands_applied
71
+ end
72
+
51
73
  def fetcher
52
74
  @fetcher ||= :fetch
53
75
  end
@@ -56,6 +78,10 @@ module Yaoc
56
78
  self.fetcher = new_fetcher
57
79
  end
58
80
 
81
+ def with_strategy(new_strategy)
82
+ self.strategy = new_strategy
83
+ end
84
+
59
85
  def build_commands_ordered
60
86
  if command_order == :recorded_order
61
87
  build_commands
@@ -4,16 +4,18 @@ module Yaoc
4
4
  attr_accessor :load_result_source, :dump_result_source
5
5
 
6
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)}
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)}
9
9
  end
10
10
 
11
11
  def load(fetch_able)
12
- load_result_source.call(converter(fetch_able).call())
12
+ converter_result = converter(fetch_able).call()
13
+ call_constructor(load_result_source, converter_result)
13
14
  end
14
15
 
15
16
  def dump(object)
16
- dump_result_source.call(reverse_converter(object).call())
17
+ converter_result = reverse_converter(object).call()
18
+ call_constructor(dump_result_source, converter_result)
17
19
  end
18
20
 
19
21
  def add_mapping(&block)
@@ -23,12 +25,22 @@ module Yaoc
23
25
 
24
26
  protected
25
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
34
+ end
35
+
26
36
  def apply_commands
27
37
  converter_builder.apply_commands!
28
38
  reverse_converter_builder.apply_commands!
29
39
  end
30
40
 
31
- def rule(to: nil, from: to, converter: nil, reverse_converter: nil)
41
+ def rule(to: nil, from: to, converter: nil,
42
+ reverse_to: from, reverse_from: to, reverse_converter: nil)
43
+
32
44
  converter_builder.rule(
33
45
  to: to,
34
46
  from: from,
@@ -36,8 +48,8 @@ module Yaoc
36
48
  )
37
49
 
38
50
  reverse_converter_builder.rule(
39
- to: from,
40
- from: to,
51
+ to: reverse_to,
52
+ from: reverse_from,
41
53
  converter: reverse_converter,
42
54
  )
43
55
  end
@@ -50,6 +62,14 @@ module Yaoc
50
62
  reverse_converter_builder.fetcher = new_fetcher
51
63
  end
52
64
 
65
+ def strategy(new_strategy)
66
+ converter_builder.strategy = new_strategy
67
+ end
68
+
69
+ def reverse_strategy(new_strategy)
70
+ reverse_converter_builder.strategy = new_strategy
71
+ end
72
+
53
73
  def converter(fetch_able)
54
74
  converter_builder.converter(fetch_able)
55
75
  end
data/lib/yaoc/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Yaoc
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -51,7 +51,7 @@ feature "Map objects", %q{
51
51
  end
52
52
  }
53
53
 
54
- given(:input_hash){
54
+ given(:input_object){
55
55
  dump_result_object
56
56
  }
57
57
 
@@ -66,7 +66,7 @@ feature "Map objects", %q{
66
66
  scenario "creates an result object from an input_object" do
67
67
  load_result_object.name += " Hello World"
68
68
 
69
- expect(mapper.load(input_hash)).to eq load_result_object
69
+ expect(mapper.load(input_object)).to eq load_result_object
70
70
  end
71
71
 
72
72
  scenario "dumps an result object as result object" do
@@ -0,0 +1,67 @@
1
+ require "spec_helper"
2
+
3
+ feature "Map objects", %q{
4
+ In order to map objects with positional constructors
5
+ as a lib user
6
+ I want to map object from an input object to an output object and reverse with a given mapping strategy
7
+ } do
8
+
9
+ given(:mapper){
10
+ Yaoc::ObjectMapper.new(load_result_object_class, dump_result_object_class).tap do |mapper|
11
+ mapper.add_mapping do
12
+ fetcher :public_send
13
+ reverse_fetcher :public_send
14
+
15
+ strategy :to_array_mapping
16
+
17
+ rule to: 0, from: :id,
18
+ reverse_from: :id
19
+
20
+ rule to: 1, from: :name,
21
+ reverse_from: :name
22
+ end
23
+ end
24
+ }
25
+
26
+ given(:load_result_object_class) {
27
+ Struct.new(:id, :name) do
28
+ include Equalizer.new(:id, :name)
29
+ end
30
+ }
31
+
32
+ given(:dump_result_object_class) {
33
+ Struct.new(:id, :name) do
34
+ include Equalizer.new(:id, :name)
35
+
36
+ def initialize(params={})
37
+ super()
38
+
39
+ params.each do |attr, value|
40
+ self.public_send("#{attr}=", value)
41
+ end if params
42
+ end
43
+
44
+ end
45
+ }
46
+
47
+ given(:input_object){
48
+ dump_result_object
49
+ }
50
+
51
+ given(:load_result_object){
52
+ load_result_object_class.new(1,"paul")
53
+ }
54
+
55
+ given(:dump_result_object){
56
+ dump_result_object_class.new({id: 1, name: "paul"})
57
+ }
58
+
59
+ scenario "creates an result object from an input_object" do
60
+ expect(mapper.load(input_object)).to eq load_result_object
61
+ end
62
+
63
+ scenario "dumps an result object as result object" do
64
+ expect(mapper.dump(load_result_object)).to eq dump_result_object
65
+ end
66
+
67
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,22 @@
1
1
  require 'bundler/setup'
2
2
  Bundler.require(:development)
3
3
 
4
+
5
+ begin
6
+ if ENV["COVERAGE"]
7
+ require 'simplecov'
8
+ SimpleCov.start do
9
+ add_group "Lib", "lib"
10
+
11
+ add_filter "/spec/"
12
+ end
13
+ end
14
+ rescue LoadError
15
+ warn "=" * 80
16
+ warn 'simplecov not installed. No coverage report'
17
+ warn "=" * 80
18
+ end
19
+
4
20
  require 'yaoc'
5
21
 
6
22
  Dir[File.join(File.expand_path(__dir__ ), "support/**/*.rb")].each { |f| require f }
@@ -48,19 +48,18 @@ describe Yaoc::ConverterBuilder do
48
48
 
49
49
  describe "#add_mapping" do
50
50
 
51
-
52
-
53
51
  it "delegates to internal methods" do
54
- expect(subject).to receive(:fetch_with).with(:public_send)
55
52
  expect(subject).to receive(:rule).with(to: :id, from: :from, converter: :converter)
56
53
 
57
54
  subject.add_mapping do
58
55
  fetch_with :public_send
56
+ with_strategy :to_array_mapping
59
57
  rule to: :id, from: :from, converter: :converter
60
58
  end
61
- end
62
-
63
59
 
60
+ expect(subject.send :fetcher).to eq(:public_send)
61
+ expect(subject.strategy).to eq(:to_array_mapping)
62
+ end
64
63
 
65
64
  end
66
65
 
@@ -95,7 +94,7 @@ describe Yaoc::ConverterBuilder do
95
94
  end
96
95
  end
97
96
 
98
- it "use the right to when from in arrays is missing" do
97
+ it "use the right 'to' when 'from' in arrays is missing" do
99
98
  expect(converter_class).to receive(:map).ordered.with(:id, :r_id, nil)
100
99
  expect(converter_class).to receive(:map).ordered.with(:name, :name, nil)
101
100
 
@@ -105,4 +104,22 @@ describe Yaoc::ConverterBuilder do
105
104
  end
106
105
  end
107
106
  end
107
+
108
+ describe "#converter" do
109
+ it "creates a new converter class with the wanted strategy" do
110
+ subject = Yaoc::ConverterBuilder.new()
111
+ subject.add_mapping do
112
+ with_strategy :to_array_mapping
113
+ end
114
+
115
+ expect(subject.converter({})).to be_kind_of Yaoc::Strategies::ToArrayMapping
116
+ end
117
+
118
+ it "raises an exception when not all commands are applied" do
119
+ subject = Yaoc::ConverterBuilder.new()
120
+ subject.strategy = :to_array_mapping
121
+
122
+ expect{subject.converter({})}.to raise_exception
123
+ end
124
+ end
108
125
  end
@@ -21,6 +21,13 @@ describe Yaoc::MappingBase do
21
21
  end
22
22
  }
23
23
 
24
+ describe "created module" do
25
+ it "can be inspected" do
26
+ subject.map(:foo, :bar)
27
+ expect(subject.class_private_module.inspect).to include("map_0000_bar_to_foo")
28
+ end
29
+ end
30
+
24
31
  describe ".map" do
25
32
 
26
33
  it "creates a bunch of mapping methods" do
@@ -62,6 +62,14 @@ describe Yaoc::ObjectMapper do
62
62
 
63
63
  end
64
64
 
65
+ 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)
67
+
68
+ subject.add_mapping do
69
+ rule to: :id, reverse_to: :id_r, reverse_from: :id_r
70
+ end
71
+ end
72
+
65
73
  it "allows to set a fetcher" do
66
74
  expect(converter_builder).to receive(:fetcher=).with(:public_send)
67
75
 
@@ -81,6 +89,24 @@ describe Yaoc::ObjectMapper do
81
89
  rule to: :id
82
90
  end
83
91
  end
92
+
93
+ it "allows to change the strategy" do
94
+ expect(converter_builder).to receive(:strategy=).with(:to_array_mapping)
95
+
96
+ subject.add_mapping do
97
+ strategy :to_array_mapping
98
+ rule to: 0, from: :id
99
+ end
100
+ end
101
+
102
+ it "allows to change the reverse strategy" do
103
+ expect(reverse_converter_builder).to receive(:strategy=).with(:to_array_mapping)
104
+
105
+ subject.add_mapping do
106
+ reverse_strategy :to_array_mapping
107
+ rule to: :id, from: 0
108
+ end
109
+ end
84
110
  end
85
111
 
86
112
  describe "#load" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yaoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dieter Späth
@@ -227,6 +227,7 @@ files:
227
227
  - lib/yaoc/strategies/to_hash_mapping.rb
228
228
  - lib/yaoc/version.rb
229
229
  - spec/acceptance/map_objects_spec.rb
230
+ - spec/acceptance/map_to_objects_with_positional_constructors_spec.rb
230
231
  - spec/spec_helper.rb
231
232
  - spec/support/feature.rb
232
233
  - spec/unit/lib/yaoc/converter_builder_spec.rb
@@ -261,6 +262,7 @@ specification_version: 4
261
262
  summary: Yet another object converter
262
263
  test_files:
263
264
  - spec/acceptance/map_objects_spec.rb
265
+ - spec/acceptance/map_to_objects_with_positional_constructors_spec.rb
264
266
  - spec/spec_helper.rb
265
267
  - spec/support/feature.rb
266
268
  - spec/unit/lib/yaoc/converter_builder_spec.rb