yaoc 0.0.3 → 0.0.4

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