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 +4 -4
- data/.gitignore +1 -0
- data/Gemfile +2 -0
- data/README.md +59 -3
- data/Rakefile +12 -0
- data/lib/yaoc/converter_builder.rb +35 -9
- data/lib/yaoc/object_mapper.rb +27 -7
- data/lib/yaoc/version.rb +1 -1
- data/spec/acceptance/map_objects_spec.rb +2 -2
- data/spec/acceptance/map_to_objects_with_positional_constructors_spec.rb +67 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/unit/lib/yaoc/converter_builder_spec.rb +23 -6
- data/spec/unit/lib/yaoc/mapping_base_spec.rb +7 -0
- data/spec/unit/lib/yaoc/object_mapper_spec.rb +26 -0
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 409ba0cb455bbdea76b8dd9f32bd81c5d7d8a6bf
|
4
|
+
data.tar.gz: 37de097336722ccd09c26c44f943a6161355ae9f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1258d989f4d14f28c806c45daac46516d0277e471906583ad999d68a662b09deb792118fc9675a06b9df50c12ecfa558a1631d5c2226d26009d10c16d485c389
|
7
|
+
data.tar.gz: b3969999352325fe98045f0b2e5d3edd153f1b12915822a93a1b44f776893a2963cf943fed7103462c882b6a845df1c64f1e79404fabbee408dfc85e7956615a
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
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
|
-
|
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
|
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
|
data/lib/yaoc/object_mapper.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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,
|
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:
|
40
|
-
from:
|
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
@@ -51,7 +51,7 @@ feature "Map objects", %q{
|
|
51
51
|
end
|
52
52
|
}
|
53
53
|
|
54
|
-
given(:
|
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(
|
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.
|
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
|