two-way-mapper 0.0.1 → 0.1.0
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 +5 -5
- data/.travis.yml +4 -4
- data/README.md +13 -4
- data/lib/two-way-mapper.rb +2 -0
- data/lib/two_way_mapper/map.rb +4 -0
- data/lib/two_way_mapper/mapping.rb +10 -7
- data/lib/two_way_mapper/node/active_record.rb +3 -1
- data/lib/two_way_mapper/node/{abstract.rb → base.rb} +19 -12
- data/lib/two_way_mapper/node/hash.rb +6 -2
- data/lib/two_way_mapper/node/object.rb +9 -5
- data/lib/two_way_mapper/node.rb +3 -1
- data/lib/two_way_mapper/railtie.rb +4 -2
- data/lib/two_way_mapper/rule.rb +7 -5
- data/lib/two_way_mapper/tools.rb +4 -2
- data/lib/two_way_mapper/version.rb +3 -1
- data/lib/two_way_mapper.rb +2 -0
- data/spec/map_spec.rb +3 -1
- data/spec/mapping_spec.rb +16 -14
- data/spec/node/active_record_spec.rb +6 -2
- data/spec/node/{abstract_spec.rb → base_spec.rb} +10 -5
- data/spec/node/hash_spec.rb +7 -3
- data/spec/node/object_spec.rb +4 -2
- data/spec/rule_spec.rb +34 -10
- data/spec/tools_spec.rb +8 -8
- data/two-way-mapper.gemspec +16 -15
- metadata +23 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 57a42be67b0c722d8983ca53b2728722a7f6547609d7d8523963402e937f377e
|
4
|
+
data.tar.gz: c91f6f0b528679ef27f9a6d544ed3261c2c5a8815613e5c74757792fc9f75022
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6fa805f14750104f9e344d9d79de4a0a75c8ed8f14d447edad29d6ecedd26b05fa3fbbfdd71870c2832779edc76dfa1a2316a03f273717d5bc3e99f9c363e46a
|
7
|
+
data.tar.gz: e38c8c4a6028b516669afe6adfb4bd9cf02da30df15aa2d13c0d0df1f1f1b9788f8e48a498785b925e5850bb5db9efc9f2583d5f163a4f0bc4c94e648a6aa3ad
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -38,6 +38,15 @@ TwoWayMapper.register :customer do |mapping|
|
|
38
38
|
end
|
39
39
|
```
|
40
40
|
|
41
|
+
Mapping can be defined explicitly without registration
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
mapping = TwoWayMapper::Mapping.new
|
45
|
+
mapping.left :object
|
46
|
+
mapping.right :hash, stringify_keys: true
|
47
|
+
# ...
|
48
|
+
```
|
49
|
+
|
41
50
|
Once mapping is defined we can convert one object to another and vice versa
|
42
51
|
|
43
52
|
```ruby
|
@@ -46,7 +55,7 @@ Customer = Struct.new :first_name, :last_name, :gender
|
|
46
55
|
customer = Customer.new
|
47
56
|
api_response = { 'FirstName' => 'Evee', 'LastName' => 'Fjord', 'sex' => 'female' }
|
48
57
|
|
49
|
-
TwoWayMapper[:customer].from_right_to_left
|
58
|
+
TwoWayMapper[:customer].from_right_to_left(customer, api_response)
|
50
59
|
puts customer.first_name # => 'Evee'
|
51
60
|
puts customer.last_name # => 'Fjord'
|
52
61
|
puts customer.gender # => 'F'
|
@@ -58,17 +67,17 @@ another_customer.first_name = 'Step'
|
|
58
67
|
another_customer.last_name = 'Bander'
|
59
68
|
another_customer.gender = 'M'
|
60
69
|
|
61
|
-
TwoWayMapper[:customer].from_left_to_right
|
70
|
+
TwoWayMapper[:customer].from_left_to_right(another_customer, request_data)
|
62
71
|
puts request_data # => { 'FirstName' => 'Step', 'LastName' => 'Bander', sex: 'male' }
|
63
72
|
```
|
64
73
|
|
65
|
-
|
74
|
+
In rails, mappings can be defined in `app/mappings` folder
|
66
75
|
|
67
76
|
### Available plugins
|
68
77
|
|
69
78
|
* hash
|
70
79
|
* object
|
71
|
-
* active_record (same as object
|
80
|
+
* active_record (same as `object`, but for keys like `user.email`, it builds `user` before updating `email` on write)
|
72
81
|
|
73
82
|
## Contributing
|
74
83
|
|
data/lib/two-way-mapper.rb
CHANGED
data/lib/two_way_mapper/map.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module TwoWayMapper
|
2
4
|
class Map
|
3
5
|
delegate :[], to: :@maps
|
@@ -8,7 +10,9 @@ module TwoWayMapper
|
|
8
10
|
|
9
11
|
def register(name)
|
10
12
|
mapping = TwoWayMapper::Mapping.new
|
13
|
+
|
11
14
|
yield mapping if block_given?
|
15
|
+
|
12
16
|
@maps[name.to_sym] = mapping
|
13
17
|
end
|
14
18
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module TwoWayMapper
|
2
4
|
class Mapping
|
3
5
|
attr_reader :rules, :left_class, :left_options, :right_class, :right_options
|
@@ -9,14 +11,14 @@ module TwoWayMapper
|
|
9
11
|
[:left, :right].each do |method|
|
10
12
|
class_eval <<-CODE, __FILE__, __LINE__ + 1
|
11
13
|
def #{method}(plugin, options = {})
|
12
|
-
@#{method}_class = node_class
|
14
|
+
@#{method}_class = node_class(plugin)
|
13
15
|
@#{method}_options = options
|
14
16
|
end
|
15
17
|
CODE
|
16
18
|
end
|
17
19
|
|
18
20
|
def node_class(plugin)
|
19
|
-
TwoWayMapper::Node.const_get
|
21
|
+
TwoWayMapper::Node.const_get(plugin.to_s.camelize)
|
20
22
|
rescue NameError
|
21
23
|
raise NameError, 'Cannot find node'
|
22
24
|
end
|
@@ -31,15 +33,16 @@ module TwoWayMapper
|
|
31
33
|
|
32
34
|
if left_selector.is_a?(Hash)
|
33
35
|
raise ArgumentError if left_selector.count < 2
|
36
|
+
|
34
37
|
opt = left_selector
|
35
38
|
left_selector = opt.keys.first
|
36
|
-
left_opt.merge! opt.delete
|
39
|
+
left_opt.merge! opt.delete(left_selector)
|
37
40
|
right_selector = opt.keys.first
|
38
|
-
right_opt.merge!
|
41
|
+
right_opt.merge!(opt.delete(right_selector))
|
39
42
|
end
|
40
43
|
|
41
|
-
left = left_class.new
|
42
|
-
right = right_class.new
|
44
|
+
left = left_class.new(left_selector, left_options.merge(left_opt))
|
45
|
+
right = right_class.new(right_selector, right_options.merge(right_opt))
|
43
46
|
|
44
47
|
@rules << Rule.new(left, right, opt)
|
45
48
|
end
|
@@ -47,7 +50,7 @@ module TwoWayMapper
|
|
47
50
|
{ left: :right, right: :left }.each do |from, to|
|
48
51
|
class_eval <<-CODE, __FILE__, __LINE__ + 1
|
49
52
|
def from_#{from}_to_#{to}(left_obj, right_obj)
|
50
|
-
rules.each { |r| r.from_#{from}_to_#{to}
|
53
|
+
rules.each { |r| r.from_#{from}_to_#{to}(left_obj, right_obj) }
|
51
54
|
#{to}_obj
|
52
55
|
end
|
53
56
|
CODE
|
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module TwoWayMapper
|
2
4
|
module Node
|
3
|
-
class
|
5
|
+
class Base
|
4
6
|
DIVIDER = '.'
|
5
7
|
|
6
8
|
attr_accessor :selector, :options
|
@@ -14,47 +16,52 @@ module TwoWayMapper
|
|
14
16
|
block = options[:stringify_keys] ? :to_s : :to_sym
|
15
17
|
block = block.to_proc
|
16
18
|
end
|
17
|
-
selector.split(DIVIDER).map
|
19
|
+
selector.split(DIVIDER).map(&block)
|
18
20
|
end
|
19
21
|
|
20
22
|
def read(source)
|
21
|
-
rewind_forward(source) { |
|
23
|
+
rewind_forward(source) { |_obj, _key| return nil }
|
22
24
|
end
|
23
25
|
|
24
|
-
def write(
|
26
|
+
def write(_obj, _value)
|
27
|
+
raise NotImplementedError
|
25
28
|
end
|
26
29
|
|
27
30
|
def writable?(current_value, new_value)
|
28
31
|
!options[:write_if] ||
|
29
|
-
|
30
|
-
|
32
|
+
!options[:write_if].respond_to?(:call) ||
|
33
|
+
options[:write_if].call(current_value, new_value)
|
31
34
|
end
|
32
35
|
|
33
36
|
private
|
34
37
|
|
35
38
|
def rewind_forward(obj, margin = 0)
|
36
39
|
to = -(1 + margin.to_i.abs)
|
40
|
+
|
37
41
|
keys[0..to].each do |key|
|
38
42
|
unless rewind_to?(obj, key)
|
39
43
|
if block_given?
|
40
|
-
yield
|
44
|
+
yield(obj, key)
|
41
45
|
else
|
42
|
-
create_node
|
46
|
+
create_node(obj, key)
|
43
47
|
end
|
44
48
|
end
|
45
|
-
obj = next_key
|
49
|
+
obj = next_key(obj, key)
|
46
50
|
end
|
47
51
|
|
48
52
|
obj
|
49
53
|
end
|
50
54
|
|
51
|
-
def rewind_to?(
|
55
|
+
def rewind_to?(_obj, _key)
|
56
|
+
raise NotImplementedError
|
52
57
|
end
|
53
58
|
|
54
|
-
def create_node(
|
59
|
+
def create_node(_obj, _key)
|
60
|
+
raise NotImplementedError
|
55
61
|
end
|
56
62
|
|
57
|
-
def next_key(
|
63
|
+
def next_key(_obj, _key)
|
64
|
+
raise NotImplementedError
|
58
65
|
end
|
59
66
|
end
|
60
67
|
end
|
@@ -1,10 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module TwoWayMapper
|
2
4
|
module Node
|
3
|
-
class Hash <
|
5
|
+
class Hash < Base
|
4
6
|
def write(source, value)
|
5
7
|
rewinded = rewind_forward source, 1
|
6
8
|
|
7
|
-
|
9
|
+
return unless writable?(rewinded[keys.last], value)
|
10
|
+
|
11
|
+
rewinded[keys.last] = value
|
8
12
|
end
|
9
13
|
|
10
14
|
private
|
@@ -1,23 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module TwoWayMapper
|
2
4
|
module Node
|
3
|
-
class Object <
|
5
|
+
class Object < Base
|
4
6
|
def write(source, value)
|
5
|
-
rewinded = rewind_forward
|
7
|
+
rewinded = rewind_forward(source, 1)
|
8
|
+
|
9
|
+
return unless writable?(rewinded.send(keys.last), value)
|
6
10
|
|
7
|
-
rewinded.send
|
11
|
+
rewinded.send("#{keys.last}=", value)
|
8
12
|
end
|
9
13
|
|
10
14
|
private
|
11
15
|
|
12
16
|
def rewind_to?(obj, key)
|
13
|
-
obj.respond_to?
|
17
|
+
obj.respond_to?(key)
|
14
18
|
end
|
15
19
|
|
16
20
|
def create_node(obj, key)
|
17
21
|
end
|
18
22
|
|
19
23
|
def next_key(obj, key)
|
20
|
-
obj.send
|
24
|
+
obj.send(key)
|
21
25
|
end
|
22
26
|
end
|
23
27
|
end
|
data/lib/two_way_mapper/node.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module TwoWayMapper
|
2
4
|
module Node
|
3
5
|
extend ActiveSupport::Autoload
|
4
6
|
|
5
|
-
autoload :
|
7
|
+
autoload :Base, 'two_way_mapper/node/base'
|
6
8
|
autoload :Hash, 'two_way_mapper/node/hash'
|
7
9
|
autoload :Object, 'two_way_mapper/node/object'
|
8
10
|
autoload :ActiveRecord, 'two_way_mapper/node/active_record'
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rails'
|
2
4
|
|
3
5
|
module TwoWayMapper
|
4
6
|
class Railtie < Rails::Railtie
|
5
|
-
initializer
|
7
|
+
initializer 'two_way_mapper.set_load_path' do |app|
|
6
8
|
path = Rails.root.join('app', 'mappings', '*.rb').to_s
|
7
|
-
Dir[path].each{ |file| load file }
|
9
|
+
Dir[path].each { |file| load file }
|
8
10
|
end
|
9
11
|
end
|
10
12
|
end
|
data/lib/two_way_mapper/rule.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module TwoWayMapper
|
2
4
|
class Rule
|
3
5
|
attr_reader :left, :right
|
@@ -11,12 +13,12 @@ module TwoWayMapper
|
|
11
13
|
{ left: :right, right: :left }.each do |from, to|
|
12
14
|
class_eval <<-CODE, __FILE__, __LINE__ + 1
|
13
15
|
def from_#{from}_to_#{to}(left_obj, right_obj)
|
14
|
-
value = #{from}.read
|
15
|
-
value = map_value
|
16
|
-
if @options[:on_#{from}_to_#{to}].respond_to?
|
17
|
-
value = @options[:on_#{from}_to_#{to}].call
|
16
|
+
value = #{from}.read(#{from}_obj)
|
17
|
+
value = map_value(value, #{(from == :left).inspect})
|
18
|
+
if @options[:on_#{from}_to_#{to}].respond_to?(:call)
|
19
|
+
value = @options[:on_#{from}_to_#{to}].call(value)
|
18
20
|
end
|
19
|
-
#{to}.write
|
21
|
+
#{to}.write(#{to}_obj, value)
|
20
22
|
|
21
23
|
#{to}_obj
|
22
24
|
end
|
data/lib/two_way_mapper/tools.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module TwoWayMapper
|
2
4
|
module Tools
|
3
5
|
class << self
|
4
6
|
def first_item_from_hash!(hash)
|
5
7
|
raise ArgumentError unless hash.is_a?(Hash)
|
6
|
-
raise ArgumentError unless first = hash.first
|
8
|
+
raise ArgumentError unless (first = hash.first)
|
7
9
|
|
8
|
-
hash.delete
|
10
|
+
hash.delete(first[0])
|
9
11
|
first
|
10
12
|
end
|
11
13
|
end
|
data/lib/two_way_mapper.rb
CHANGED
data/spec/map_spec.rb
CHANGED
data/spec/mapping_spec.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
describe TwoWayMapper::Mapping do
|
4
|
+
let(:mapping) { described_class.new }
|
5
|
+
|
2
6
|
[:left, :right].each do |method|
|
3
7
|
describe "##{method}" do
|
4
|
-
let(:mapping) { TwoWayMapper::Mapping.new }
|
5
|
-
|
6
8
|
it "should set #{method} with options" do
|
7
9
|
mapping.send method, :object, opt1: ''
|
8
10
|
|
@@ -13,30 +15,30 @@ describe TwoWayMapper::Mapping do
|
|
13
15
|
end
|
14
16
|
|
15
17
|
describe '#rule' do
|
16
|
-
let(:mapping) { TwoWayMapper::Mapping.new }
|
17
18
|
before :each do
|
18
19
|
mapping.left :object
|
19
20
|
mapping.right :hash
|
20
21
|
end
|
21
22
|
|
22
23
|
context 'left and right validation' do
|
23
|
-
let(:mapping_without_both) {
|
24
|
-
let(:mapping_without_left) {
|
25
|
-
let(:mapping_without_right) {
|
24
|
+
let(:mapping_without_both) { described_class.new }
|
25
|
+
let(:mapping_without_left) { described_class.new }
|
26
|
+
let(:mapping_without_right) { described_class.new }
|
27
|
+
|
26
28
|
before :each do
|
27
29
|
mapping_without_left.right :hash
|
28
30
|
mapping_without_right.left :hash
|
29
31
|
end
|
30
32
|
|
31
33
|
it 'should raise error when no left or right nodes' do
|
32
|
-
expect{mapping_without_left.rule 'key', 'key'}.to raise_error
|
33
|
-
expect{mapping_without_right.rule 'key', 'key'}.to raise_error
|
34
|
-
expect{mapping_without_both.rule 'key', 'key'}.to raise_error
|
34
|
+
expect { mapping_without_left.rule 'key', 'key' }.to raise_error StandardError
|
35
|
+
expect { mapping_without_right.rule 'key', 'key' }.to raise_error StandardError
|
36
|
+
expect { mapping_without_both.rule 'key', 'key' }.to raise_error StandardError
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
38
40
|
it 'should add item to rules hash' do
|
39
|
-
expect{mapping.rule 'key1', 'Key1'}.to change{mapping.rules.count}.from(0).to(1)
|
41
|
+
expect { mapping.rule 'key1', 'Key1' }.to change { mapping.rules.count }.from(0).to(1)
|
40
42
|
|
41
43
|
rule = mapping.rules.first
|
42
44
|
expect(rule).to be_instance_of TwoWayMapper::Rule
|
@@ -45,7 +47,7 @@ describe TwoWayMapper::Mapping do
|
|
45
47
|
end
|
46
48
|
|
47
49
|
it 'should allow to pass hash' do
|
48
|
-
expect{mapping.rule 'key1' => { opt1: 'val' }}.to raise_error
|
50
|
+
expect { mapping.rule 'key1' => { opt1: 'val' } }.to raise_error StandardError
|
49
51
|
|
50
52
|
mapping.rule 'key1' => { opt1: 'val' }, 'Key2' => {}
|
51
53
|
rule = mapping.rules.first
|
@@ -71,11 +73,11 @@ describe TwoWayMapper::Mapping do
|
|
71
73
|
end
|
72
74
|
|
73
75
|
context 'convertion methods' do
|
74
|
-
let(:mapping) { TwoWayMapper::Mapping.new }
|
75
76
|
let(:rule1) { double from_left_to_right: nil, from_right_to_left: nil }
|
76
77
|
let(:rule2) { double from_left_to_right: nil, from_right_to_left: nil }
|
77
|
-
let(:left_obj) { double
|
78
|
-
let(:right_obj) { double
|
78
|
+
let(:left_obj) { double }
|
79
|
+
let(:right_obj) { double }
|
80
|
+
|
79
81
|
before :each do
|
80
82
|
mapping.left :object
|
81
83
|
mapping.right :hash
|
@@ -1,10 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
describe TwoWayMapper::Node::ActiveRecord do
|
2
|
-
let(:node) {
|
4
|
+
let(:node) { described_class.new 'user.email' }
|
3
5
|
|
4
6
|
describe '#write' do
|
5
7
|
it 'should try to build before write' do
|
6
8
|
user = double(email: '')
|
7
|
-
obj = double
|
9
|
+
obj = double
|
10
|
+
|
8
11
|
allow(obj).to receive :build_user do
|
9
12
|
allow(obj).to receive(:user).and_return user
|
10
13
|
end
|
@@ -18,6 +21,7 @@ describe TwoWayMapper::Node::ActiveRecord do
|
|
18
21
|
it 'should try to build even if respond_to but obj itself is nil' do
|
19
22
|
user = double(email: '')
|
20
23
|
obj = double(user: nil)
|
24
|
+
|
21
25
|
allow(obj).to receive :build_user do
|
22
26
|
allow(obj).to receive(:user).and_return user
|
23
27
|
end
|
@@ -1,19 +1,24 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
describe TwoWayMapper::Node::Base do
|
2
4
|
describe '#keys' do
|
3
|
-
subject {
|
5
|
+
subject { described_class.new('key1.key11.key111') }
|
4
6
|
|
5
|
-
its(:keys) { should eql [
|
7
|
+
its(:keys) { should eql %i[key1 key11 key111] }
|
6
8
|
end
|
7
9
|
|
8
10
|
describe 'writable?' do
|
9
11
|
it 'should be truthy if write_if options not set' do
|
10
|
-
node =
|
12
|
+
node = described_class.new('key1.key11.key111')
|
11
13
|
|
12
14
|
expect(node).to be_writable 'current', 'new'
|
13
15
|
end
|
14
16
|
|
15
17
|
it 'should be truthy if write_if option set' do
|
16
|
-
node =
|
18
|
+
node = described_class.new(
|
19
|
+
'key1.key11.key111',
|
20
|
+
write_if: ->(c, n) { c == 'current' || n == 'new' }
|
21
|
+
)
|
17
22
|
|
18
23
|
expect(node).to be_writable 'current', 'new1'
|
19
24
|
expect(node).to be_writable 'current1', 'new'
|
data/spec/node/hash_spec.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
describe TwoWayMapper::Node::Hash do
|
2
4
|
context 'normal keys' do
|
3
|
-
let(:node) {
|
5
|
+
let(:node) { described_class.new('key1.key11.key111') }
|
4
6
|
|
5
7
|
describe '#read' do
|
6
8
|
it 'should return nil when path is not avaiable' do
|
@@ -25,7 +27,9 @@ describe TwoWayMapper::Node::Hash do
|
|
25
27
|
end
|
26
28
|
|
27
29
|
context 'string keys' do
|
28
|
-
let(:node)
|
30
|
+
let(:node) do
|
31
|
+
described_class.new('key1.key11.key111', stringify_keys: true)
|
32
|
+
end
|
29
33
|
|
30
34
|
describe '#read' do
|
31
35
|
it 'should return nil when path is not avaiable' do
|
@@ -50,7 +54,7 @@ describe TwoWayMapper::Node::Hash do
|
|
50
54
|
end
|
51
55
|
|
52
56
|
context 'write_if option' do
|
53
|
-
let(:node) {
|
57
|
+
let(:node) { described_class.new 'key1.key11', write_if: ->(c, n) { c.empty? || n == 'value1' } }
|
54
58
|
let(:writable_obj1) { { key1: { key11: '' } } }
|
55
59
|
let(:writable_obj2) { { key1: { key11: 'smth' } } }
|
56
60
|
let(:not_writable_obj) { { key1: { key11: 'smth' } } }
|
data/spec/node/object_spec.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
describe TwoWayMapper::Node::Object do
|
2
|
-
let(:node) {
|
4
|
+
let(:node) { described_class.new 'key1.key11.key111' }
|
3
5
|
|
4
6
|
describe '#read' do
|
5
7
|
it 'should return nil when path is not avaiable' do
|
@@ -25,7 +27,7 @@ describe TwoWayMapper::Node::Object do
|
|
25
27
|
end
|
26
28
|
|
27
29
|
context 'write_if option' do
|
28
|
-
let(:node) {
|
30
|
+
let(:node) { described_class.new 'key', write_if: ->(c, n) { c.empty? || n == 'value1'} }
|
29
31
|
let(:writable_obj1) { OpenStruct.new key: '' }
|
30
32
|
let(:writable_obj2) { OpenStruct.new key: 'smth' }
|
31
33
|
let(:not_writable_obj) { OpenStruct.new key: 'smth' }
|
data/spec/rule_spec.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
describe TwoWayMapper::Rule do
|
2
4
|
context 'transformation methods' do
|
3
|
-
let(:left_node) { TwoWayMapper::Node::Object.new
|
4
|
-
let(:right_node) { TwoWayMapper::Node::Hash.new
|
5
|
+
let(:left_node) { TwoWayMapper::Node::Object.new('key1') }
|
6
|
+
let(:right_node) { TwoWayMapper::Node::Hash.new('Kk.Key1') }
|
5
7
|
let(:left_object) { OpenStruct.new }
|
6
8
|
let(:map) { { 'value' => 'VALUE' } }
|
7
9
|
|
8
10
|
context 'without options' do
|
9
|
-
let(:rule) {
|
11
|
+
let(:rule) { described_class.new left_node, right_node }
|
10
12
|
|
11
13
|
describe '#from_left_to_right' do
|
12
14
|
it 'should read from left node and write to right node' do
|
@@ -30,7 +32,7 @@ describe TwoWayMapper::Rule do
|
|
30
32
|
end
|
31
33
|
|
32
34
|
context 'with map option' do
|
33
|
-
let(:rule) {
|
35
|
+
let(:rule) { described_class.new left_node, right_node, map: map, default: 'not found' }
|
34
36
|
|
35
37
|
describe '#from_left_to_right' do
|
36
38
|
it 'should read from left node and write to right node' do
|
@@ -56,7 +58,7 @@ describe TwoWayMapper::Rule do
|
|
56
58
|
context 'with default option' do
|
57
59
|
describe '#from_left_to_right' do
|
58
60
|
it 'should return default value if not found' do
|
59
|
-
rule =
|
61
|
+
rule = described_class.new left_node, right_node, map: map, default: 'not found'
|
60
62
|
|
61
63
|
left_object.key1 = 'value1'
|
62
64
|
right_object = {}
|
@@ -66,7 +68,14 @@ describe TwoWayMapper::Rule do
|
|
66
68
|
end
|
67
69
|
|
68
70
|
it 'should return use default_left if present and value not found' do
|
69
|
-
rule =
|
71
|
+
rule = described_class.new(
|
72
|
+
left_node,
|
73
|
+
right_node,
|
74
|
+
map: map,
|
75
|
+
default: 'not found',
|
76
|
+
default_left: 'not found on left',
|
77
|
+
default_right: 'not found on right'
|
78
|
+
)
|
70
79
|
|
71
80
|
left_object.key1 = 'value1'
|
72
81
|
right_object = {}
|
@@ -78,7 +87,7 @@ describe TwoWayMapper::Rule do
|
|
78
87
|
|
79
88
|
describe '#from_right_to_left' do
|
80
89
|
it 'should return default value if not found' do
|
81
|
-
rule =
|
90
|
+
rule = described_class.new left_node, right_node, map: map, default: 'not found'
|
82
91
|
|
83
92
|
left_object.key1 = nil
|
84
93
|
right_object = { Kk: { Key1: 'VALUE1' } }
|
@@ -88,7 +97,14 @@ describe TwoWayMapper::Rule do
|
|
88
97
|
end
|
89
98
|
|
90
99
|
it 'should return use default_right if present and value not found' do
|
91
|
-
rule =
|
100
|
+
rule = described_class.new(
|
101
|
+
left_node,
|
102
|
+
right_node,
|
103
|
+
map: map,
|
104
|
+
default: 'not found',
|
105
|
+
default_left: 'not found on left',
|
106
|
+
default_right: 'not found on right'
|
107
|
+
)
|
92
108
|
|
93
109
|
left_object.key1 = nil
|
94
110
|
right_object = { Kk: { Key1: 'VALUE1' } }
|
@@ -102,7 +118,11 @@ describe TwoWayMapper::Rule do
|
|
102
118
|
describe 'with callback option' do
|
103
119
|
describe 'on_left_to_right' do
|
104
120
|
it 'should transform value if such options passed' do
|
105
|
-
rule =
|
121
|
+
rule = described_class.new(
|
122
|
+
left_node,
|
123
|
+
right_node,
|
124
|
+
on_left_to_right: ->(v) { v.upcase }
|
125
|
+
)
|
106
126
|
|
107
127
|
left_object.key1 = 'value1'
|
108
128
|
right_object = {}
|
@@ -114,7 +134,11 @@ describe TwoWayMapper::Rule do
|
|
114
134
|
|
115
135
|
describe 'on_right_to_left' do
|
116
136
|
it 'should transform value if such options passed' do
|
117
|
-
rule =
|
137
|
+
rule = described_class.new(
|
138
|
+
left_node,
|
139
|
+
right_node,
|
140
|
+
on_right_to_left: ->(v) { v.downcase }
|
141
|
+
)
|
118
142
|
|
119
143
|
left_object.key1 = nil
|
120
144
|
right_object = { Kk: { Key1: 'VALUE1' } }
|
data/spec/tools_spec.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
|
-
|
2
|
-
let(:tools) { TwoWayMapper::Tools }
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
3
|
+
describe TwoWayMapper::Tools do
|
4
4
|
describe '.first_item_from_hash!' do
|
5
5
|
it 'should raise error unless hash passed' do
|
6
|
-
expect{
|
7
|
-
expect{
|
8
|
-
expect{
|
6
|
+
expect { described_class.first_item_from_hash! }.to raise_error ArgumentError
|
7
|
+
expect { described_class.first_item_from_hash! '' }.to raise_error ArgumentError
|
8
|
+
expect { described_class.first_item_from_hash! 1 }.to raise_error ArgumentError
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'should raise error if emplt hash passed' do
|
12
|
-
expect{
|
12
|
+
expect { described_class.first_item_from_hash! {} }.to raise_error ArgumentError
|
13
13
|
end
|
14
14
|
|
15
15
|
it 'should return first hash key and value' do
|
16
|
-
k, v =
|
16
|
+
k, v = described_class.first_item_from_hash! a: 1
|
17
17
|
|
18
18
|
expect(k).to eql :a
|
19
19
|
expect(v).to eql 1
|
@@ -21,7 +21,7 @@ describe TwoWayMapper::Tools do
|
|
21
21
|
|
22
22
|
it 'should delete first item' do
|
23
23
|
hash = { a: 1, b: 2 }
|
24
|
-
|
24
|
+
_k, _v = described_class.first_item_from_hash!(hash)
|
25
25
|
|
26
26
|
expect(hash).not_to include a: 1
|
27
27
|
end
|
data/two-way-mapper.gemspec
CHANGED
@@ -1,27 +1,28 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'two_way_mapper/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
8
|
+
spec.name = 'two-way-mapper'
|
8
9
|
spec.version = TwoWayMapper::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.description =
|
12
|
-
spec.summary =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
10
|
+
spec.authors = ['Tim Masliuchenko']
|
11
|
+
spec.email = ['insside@gmail.com']
|
12
|
+
spec.description = 'Two way data mapping'
|
13
|
+
spec.summary = 'Two way data mapping'
|
14
|
+
spec.homepage = 'https://github.com/timsly/two-way-mapper'
|
15
|
+
spec.license = 'MIT'
|
15
16
|
|
16
|
-
spec.files = `git ls-files`.split(
|
17
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
17
18
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = [
|
20
|
+
spec.require_paths = ['lib']
|
20
21
|
|
21
|
-
spec.add_dependency
|
22
|
+
spec.add_dependency 'activesupport'
|
22
23
|
|
23
|
-
spec.add_development_dependency
|
24
|
-
spec.add_development_dependency
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
24
|
+
spec.add_development_dependency 'bundler'
|
25
|
+
spec.add_development_dependency 'rake'
|
26
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
27
|
+
spec.add_development_dependency 'rspec-its'
|
27
28
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: two-way-mapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Tim Masliuchenko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-12-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -28,46 +28,46 @@ dependencies:
|
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name: rspec
|
56
|
+
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
61
|
+
version: '3.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
68
|
+
version: '3.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: rspec-its
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
@@ -101,8 +101,8 @@ files:
|
|
101
101
|
- lib/two_way_mapper/map.rb
|
102
102
|
- lib/two_way_mapper/mapping.rb
|
103
103
|
- lib/two_way_mapper/node.rb
|
104
|
-
- lib/two_way_mapper/node/abstract.rb
|
105
104
|
- lib/two_way_mapper/node/active_record.rb
|
105
|
+
- lib/two_way_mapper/node/base.rb
|
106
106
|
- lib/two_way_mapper/node/hash.rb
|
107
107
|
- lib/two_way_mapper/node/object.rb
|
108
108
|
- lib/two_way_mapper/railtie.rb
|
@@ -111,15 +111,15 @@ files:
|
|
111
111
|
- lib/two_way_mapper/version.rb
|
112
112
|
- spec/map_spec.rb
|
113
113
|
- spec/mapping_spec.rb
|
114
|
-
- spec/node/abstract_spec.rb
|
115
114
|
- spec/node/active_record_spec.rb
|
115
|
+
- spec/node/base_spec.rb
|
116
116
|
- spec/node/hash_spec.rb
|
117
117
|
- spec/node/object_spec.rb
|
118
118
|
- spec/rule_spec.rb
|
119
119
|
- spec/spec_helper.rb
|
120
120
|
- spec/tools_spec.rb
|
121
121
|
- two-way-mapper.gemspec
|
122
|
-
homepage:
|
122
|
+
homepage: https://github.com/timsly/two-way-mapper
|
123
123
|
licenses:
|
124
124
|
- MIT
|
125
125
|
metadata: {}
|
@@ -138,16 +138,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
138
|
- !ruby/object:Gem::Version
|
139
139
|
version: '0'
|
140
140
|
requirements: []
|
141
|
-
|
142
|
-
rubygems_version: 2.2.2
|
141
|
+
rubygems_version: 3.0.3
|
143
142
|
signing_key:
|
144
143
|
specification_version: 4
|
145
144
|
summary: Two way data mapping
|
146
145
|
test_files:
|
147
146
|
- spec/map_spec.rb
|
148
147
|
- spec/mapping_spec.rb
|
149
|
-
- spec/node/abstract_spec.rb
|
150
148
|
- spec/node/active_record_spec.rb
|
149
|
+
- spec/node/base_spec.rb
|
151
150
|
- spec/node/hash_spec.rb
|
152
151
|
- spec/node/object_spec.rb
|
153
152
|
- spec/rule_spec.rb
|