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