yaoc 0.0.1
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 +7 -0
- data/.gitignore +18 -0
- data/Gemfile +5 -0
- data/Guardfile +23 -0
- data/LICENSE.txt +22 -0
- data/README.md +54 -0
- data/Rakefile +1 -0
- data/lib/yaoc.rb +11 -0
- data/lib/yaoc/mapping_base.rb +57 -0
- data/lib/yaoc/object_mapper.rb +71 -0
- data/lib/yaoc/strategies/to_array_mapping.rb +25 -0
- data/lib/yaoc/strategies/to_hash_mapping.rb +23 -0
- data/lib/yaoc/version.rb +3 -0
- data/spec/acceptance/map_objects_spec.rb +56 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support/feature.rb +30 -0
- data/spec/unit/lib/yaoc/mapping_base_spec.rb +86 -0
- data/spec/unit/lib/yaoc/object_mapper_spec.rb +105 -0
- data/spec/unit/lib/yaoc/strategies/to_array_mapping_spec.rb +77 -0
- data/spec/unit/lib/yaoc/strategies/to_hash_mapping_spec.rb +84 -0
- data/yaoc.gemspec +48 -0
- metadata +267 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: df536899f7147ce6f470564bab83b8d81db904d7
|
4
|
+
data.tar.gz: 46dbdfd57424ae671873eafaf678ce5a590588c5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f111573c5f28bfc0c2e459d50c75c8dcbdc8b221c19f833ed9738a64e05caface3ef3c620a12370c55b0a97141376f63fb35fc9e42e90f9447399807d1ade6c7
|
7
|
+
data.tar.gz: c33e319c2d3278aed77877fae3add31de7c0b1ddf49ea044db3a245ac9a6fa50e0831b6e689e7d5f4b8c271d9d4c6ef698f5cf9435fc3af7e581cc9f81447405
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard :rspec, all_after_pass: true ,
|
5
|
+
all_on_start: true do
|
6
|
+
|
7
|
+
watch(%r{^spec/.+_spec\.rb$})
|
8
|
+
|
9
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/unit/lib/#{m[1]}_spec.rb" }
|
10
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/integration/lib/#{m[1]}_spec.rb" }
|
11
|
+
|
12
|
+
watch('spec/spec_helper.rb') { "spec" }
|
13
|
+
|
14
|
+
watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
guard :bundler do
|
20
|
+
watch('Gemfile')
|
21
|
+
# Uncomment next line if your Gemfile contains the `gemspec' command.
|
22
|
+
watch(/^.+\.gemspec/)
|
23
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Dieter Späth
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Yaoc
|
2
|
+
|
3
|
+
Indentation of this gem is to learn and train a little ruby.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'yaoc'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install yaoc
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Uptodate doc's look into the specs.
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
|
25
|
+
User = Struct.new(:id, :name) do
|
26
|
+
def initialize(params={})
|
27
|
+
super()
|
28
|
+
|
29
|
+
params.each do |attr, value|
|
30
|
+
self.public_send("#{attr}=", value)
|
31
|
+
end if params
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
mapper = Yaoc::ObjectMapper.new(User).tap do |mapper|
|
36
|
+
mapper.add_mapping do
|
37
|
+
rule to: :name, from: :fullname
|
38
|
+
rule to: :id
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
user = mapper.load({id: 1, fullname: "myname" })
|
44
|
+
|
45
|
+
|
46
|
+
```
|
47
|
+
|
48
|
+
## Contributing
|
49
|
+
|
50
|
+
1. Fork it ( http://github.com/<my-github-username>/yaoc/fork )
|
51
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
52
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
53
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
54
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/yaoc.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module Yaoc
|
2
|
+
module MappingBase
|
3
|
+
include AbstractType
|
4
|
+
|
5
|
+
|
6
|
+
def self.included(other)
|
7
|
+
other.extend(ClassMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
abstract_method :call
|
11
|
+
|
12
|
+
def converter_methods
|
13
|
+
self.class.converter_methods
|
14
|
+
end
|
15
|
+
|
16
|
+
def fetcher
|
17
|
+
defined?(super) ? super : :fetch
|
18
|
+
end
|
19
|
+
|
20
|
+
module ClassMethods
|
21
|
+
include AbstractType
|
22
|
+
|
23
|
+
abstract_method :converter_proc
|
24
|
+
|
25
|
+
def map(to, from, block=nil)
|
26
|
+
class_private_module(:Mapping).tap do |mod|
|
27
|
+
mod.send :define_method, "map_#{"%04d" %[converter_methods.count]}_#{from}_to_#{to}".to_sym, (block || converter_proc(to, from))
|
28
|
+
include mod
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def converter_methods
|
33
|
+
class_private_module(:Mapping).instance_methods(false).sort
|
34
|
+
end
|
35
|
+
|
36
|
+
# inspired by Avdi Grimm, rubytapas.com 028-macros-and-modules
|
37
|
+
def class_private_module(name=:Mapping)
|
38
|
+
|
39
|
+
if const_defined?(name, false)
|
40
|
+
const_get(name)
|
41
|
+
else
|
42
|
+
new_mod = Module.new do
|
43
|
+
def self.to_s
|
44
|
+
"Mapping (#{instance_methods(false).join(', ')})"
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.inspect
|
48
|
+
to_s
|
49
|
+
end
|
50
|
+
end
|
51
|
+
const_set(name, new_mod)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Yaoc
|
2
|
+
|
3
|
+
class ObjectMapper
|
4
|
+
attr_accessor :result_class
|
5
|
+
|
6
|
+
def initialize(result_class)
|
7
|
+
self.result_class = result_class
|
8
|
+
end
|
9
|
+
|
10
|
+
def load(fetch_able)
|
11
|
+
call = converter(fetch_able).call()
|
12
|
+
|
13
|
+
result_class.new(call)
|
14
|
+
end
|
15
|
+
|
16
|
+
def dump(object)
|
17
|
+
reverse_converter(object).call()
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_mapping(&block)
|
21
|
+
instance_eval &block
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def rule(to: nil, from: to, converter: nil, reverse_converter: nil)
|
27
|
+
converter_class.map(to, from, converter)
|
28
|
+
reverse_converter_class.map(from, to, reverse_converter)
|
29
|
+
end
|
30
|
+
|
31
|
+
def fetcher(new_fetcher)
|
32
|
+
@fetcher= new_fetcher
|
33
|
+
end
|
34
|
+
|
35
|
+
def fetcher_method
|
36
|
+
@fetcher ||= :fetch
|
37
|
+
end
|
38
|
+
|
39
|
+
def reverse_fetcher(new_fetcher)
|
40
|
+
@reverse_fetcher = new_fetcher
|
41
|
+
end
|
42
|
+
|
43
|
+
def reverse_fetcher_method
|
44
|
+
@reverse_fetcher ||= :public_send
|
45
|
+
end
|
46
|
+
|
47
|
+
def converter(fetch_able)
|
48
|
+
converter_class.new(fetch_able, fetcher_method)
|
49
|
+
end
|
50
|
+
|
51
|
+
def converter_class
|
52
|
+
@converter_class ||= new_converter_class
|
53
|
+
end
|
54
|
+
|
55
|
+
def reverse_converter(fetch_able)
|
56
|
+
reverse_converter_class.new(fetch_able, reverse_fetcher_method)
|
57
|
+
end
|
58
|
+
|
59
|
+
def reverse_converter_class
|
60
|
+
@reverse_converter_class ||= new_converter_class
|
61
|
+
end
|
62
|
+
|
63
|
+
def new_converter_class
|
64
|
+
Struct.new(:to_convert, :fetcher) do
|
65
|
+
include MappingBase
|
66
|
+
include Strategies::ToHashMapping
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Yaoc
|
2
|
+
module Strategies
|
3
|
+
module ToArrayMapping
|
4
|
+
def self.included(other)
|
5
|
+
other.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
def call
|
9
|
+
[].tap do |result|
|
10
|
+
converter_methods.each do |method_name|
|
11
|
+
self.public_send(method_name, to_convert, result)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
def converter_proc(to, from)
|
18
|
+
-> (to_convert, result){
|
19
|
+
result[to] = to_convert.public_send(fetcher, from)
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Yaoc
|
2
|
+
module Strategies
|
3
|
+
module ToHashMapping
|
4
|
+
def self.included(other)
|
5
|
+
other.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
def call
|
9
|
+
converter_methods.reduce({}) do |result, method_name|
|
10
|
+
self.public_send(method_name, to_convert, result)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
def converter_proc(to, from)
|
16
|
+
-> (to_convert, result){
|
17
|
+
result.merge({to => to_convert.public_send(fetcher, from)})
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/yaoc/version.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
feature "Map objects", %q{
|
4
|
+
In order to map object
|
5
|
+
as a lib user
|
6
|
+
I want to map object from an input object to an output object and reverse
|
7
|
+
} do
|
8
|
+
|
9
|
+
given(:mapper){
|
10
|
+
Yaoc::ObjectMapper.new(result_object_class).tap do |mapper|
|
11
|
+
mapper.add_mapping do
|
12
|
+
fetcher :[]
|
13
|
+
reverse_fetcher :public_send
|
14
|
+
rule to: :name,
|
15
|
+
converter: ->(source, result){ result.merge({name: "#{source[:name]} Hello World"}) },
|
16
|
+
reverse_converter: ->(source, result){ result.merge({name: source.name}) }
|
17
|
+
rule to: :role, from: :fullrolename
|
18
|
+
rule to: :id
|
19
|
+
end
|
20
|
+
end
|
21
|
+
}
|
22
|
+
|
23
|
+
given(:result_object_class) {
|
24
|
+
Struct.new(:id, :name, :role) do
|
25
|
+
include Equalizer.new(:id, :name, :role)
|
26
|
+
|
27
|
+
def initialize(params={})
|
28
|
+
super()
|
29
|
+
|
30
|
+
params.each do |attr, value|
|
31
|
+
self.public_send("#{attr}=", value)
|
32
|
+
end if params
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
}
|
37
|
+
|
38
|
+
given(:input_hash){
|
39
|
+
{id: 1, name: "paul", fullrolename: "admin"}
|
40
|
+
}
|
41
|
+
|
42
|
+
given(:result_object){
|
43
|
+
result_object_class.new({id: 1, name: "paul", role: "admin"})
|
44
|
+
}
|
45
|
+
|
46
|
+
scenario "creates an result object from an input_object" do
|
47
|
+
result_object.name += " Hello World"
|
48
|
+
|
49
|
+
expect(mapper.load(input_hash)).to eq result_object
|
50
|
+
end
|
51
|
+
|
52
|
+
scenario "dumps an result object as hash" do
|
53
|
+
expect(mapper.dump(result_object)).to eq input_hash
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
Bundler.require(:development)
|
3
|
+
|
4
|
+
require 'yaoc'
|
5
|
+
|
6
|
+
Dir[File.join(File.expand_path(__dir__ ), "support/**/*.rb")].each { |f| require f }
|
7
|
+
|
8
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
9
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
10
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
11
|
+
# loaded once.
|
12
|
+
#
|
13
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
14
|
+
RSpec.configure do |config|
|
15
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
16
|
+
config.run_all_when_everything_filtered = true
|
17
|
+
config.filter_run :focus
|
18
|
+
|
19
|
+
# Run specs in random order to surface order dependencies. If you find an
|
20
|
+
# order dependency and want to debug it, you can fix the order by providing
|
21
|
+
# the seed, which is printed after each run.
|
22
|
+
# --seed 1234
|
23
|
+
config.order = 'random'
|
24
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#
|
2
|
+
# taken from https://github.com/jnicklas/capybara/blob/master/lib/capybara/rspec/features.rb
|
3
|
+
#
|
4
|
+
module Capybara
|
5
|
+
module Features
|
6
|
+
def self.included(base)
|
7
|
+
base.instance_eval do
|
8
|
+
alias :background :before
|
9
|
+
alias :scenario :it
|
10
|
+
alias :xscenario :xit
|
11
|
+
alias :given :let
|
12
|
+
alias :given! :let!
|
13
|
+
alias :feature :describe
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
def self.feature(*args, &block)
|
21
|
+
options = if args.last.is_a?(Hash) then args.pop else {} end
|
22
|
+
options[:capybara_feature] = true
|
23
|
+
options[:type] = :feature
|
24
|
+
options[:caller] ||= caller
|
25
|
+
args.push(options)
|
26
|
+
|
27
|
+
describe(*args, &block)
|
28
|
+
end
|
29
|
+
|
30
|
+
RSpec.configuration.include Capybara::Features, :capybara_feature => true
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Yaoc::MappingBase do
|
4
|
+
subject{
|
5
|
+
Struct.new(:to_convert) do
|
6
|
+
include Yaoc::MappingBase
|
7
|
+
|
8
|
+
def self.converter_proc(to, from)
|
9
|
+
-> (to_convert, result){
|
10
|
+
[to, from, to_convert, result]
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def call
|
15
|
+
result = :my_result
|
16
|
+
converter_methods.map do |method_name|
|
17
|
+
self.public_send(method_name, to_convert, result)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
}
|
23
|
+
|
24
|
+
describe ".map" do
|
25
|
+
|
26
|
+
it "creates a bunch of mapping methods" do
|
27
|
+
subject.map(:foo, :bar)
|
28
|
+
subject.map(:bar, :foo)
|
29
|
+
|
30
|
+
expect(subject.new(:my_to_convert).call()).to eq [[:foo, :bar, :my_to_convert, :my_result],
|
31
|
+
[:bar, :foo, :my_to_convert, :my_result]]
|
32
|
+
end
|
33
|
+
|
34
|
+
it "uses my converter when provided" do
|
35
|
+
subject.map(:bar, :foo, ->(*){})
|
36
|
+
|
37
|
+
expect(subject.new(:my_to_convert).call()).to eq [nil]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#converter_methods" do
|
42
|
+
it "preserves method order" do
|
43
|
+
subject.map(0, 1, ->(*){})
|
44
|
+
subject.map(1, :a, ->(*){})
|
45
|
+
|
46
|
+
expect(subject.converter_methods).to eq [:map_0000_1_to_0, :map_0001_a_to_1]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#fetcher" do
|
51
|
+
let(:subject_with_fetcher){
|
52
|
+
Struct.new(:to_convert) do
|
53
|
+
include Yaoc::MappingBase
|
54
|
+
|
55
|
+
def self.create_block(to, from)
|
56
|
+
-> (to_convert, result){
|
57
|
+
[to, from, to_convert, result]
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def call
|
62
|
+
result = nil
|
63
|
+
|
64
|
+
converter_methods.map do |method_name|
|
65
|
+
self.public_send(method_name, to_convert, result)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def fetcher
|
70
|
+
"my_fetcher"
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
}
|
75
|
+
|
76
|
+
it "uses in class declared fetcher" do
|
77
|
+
expect(subject_with_fetcher.new().fetcher).to eq "my_fetcher"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "uses build in fetcher without a fetcher definition" do
|
81
|
+
expect(subject.new().fetcher).to eq :fetch
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Yaoc::ObjectMapper do
|
4
|
+
subject{
|
5
|
+
Yaoc::ObjectMapper.new(Struct.new(:id, :name)).tap{|mapper|
|
6
|
+
mapper.stub(:converter_class).and_return(converter_class)
|
7
|
+
mapper.stub(:reverse_converter_class).and_return(reverse_converter_class)
|
8
|
+
}
|
9
|
+
}
|
10
|
+
|
11
|
+
let(:converter_class){
|
12
|
+
double("converter_class", map: nil, new: converter)
|
13
|
+
}
|
14
|
+
|
15
|
+
let(:reverse_converter_class){
|
16
|
+
double("reverse_converter_class", map: nil, new: reverse_converter)
|
17
|
+
}
|
18
|
+
|
19
|
+
let(:converter){
|
20
|
+
double("converter", call: nil)
|
21
|
+
}
|
22
|
+
|
23
|
+
let(:reverse_converter){
|
24
|
+
double("reverse_converter", call: nil)
|
25
|
+
}
|
26
|
+
|
27
|
+
describe "#add_mapping" do
|
28
|
+
|
29
|
+
it "creates a mapper" do
|
30
|
+
|
31
|
+
expect(converter_class).to receive(:map).with(:id, :id2, :some_proc)
|
32
|
+
subject.add_mapping do
|
33
|
+
rule to: :id,
|
34
|
+
from: :id2,
|
35
|
+
converter: :some_proc,
|
36
|
+
reverse_converter: :some_reverse_proc
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
it "creates a revers mapper" do
|
42
|
+
|
43
|
+
expect(reverse_converter_class).to receive(:map).with(:id2, :id, :some_reverse_proc)
|
44
|
+
|
45
|
+
subject.add_mapping do
|
46
|
+
rule to: :id,
|
47
|
+
from: :id2,
|
48
|
+
converter: :some_proc,
|
49
|
+
reverse_converter: :some_reverse_proc
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
it "uses defaults" do
|
55
|
+
expect(converter_class).to receive(:map).with(:id, :id, nil)
|
56
|
+
expect(reverse_converter_class).to receive(:map).with(:id, :id, nil)
|
57
|
+
|
58
|
+
subject.add_mapping do
|
59
|
+
rule to: :id
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
it "allows to set a fetcher" do
|
65
|
+
subject.add_mapping do
|
66
|
+
fetcher :public_send
|
67
|
+
rule to: :id
|
68
|
+
end
|
69
|
+
|
70
|
+
expect(subject.send :fetcher_method).to eq(:public_send)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "allows to set a reverse_fetcher" do
|
74
|
+
subject.add_mapping do
|
75
|
+
reverse_fetcher :fetch
|
76
|
+
rule to: :id
|
77
|
+
end
|
78
|
+
|
79
|
+
expect(subject.send :reverse_fetcher_method).to eq(:fetch)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "#load" do
|
84
|
+
it "creates an object of result_class kind" do
|
85
|
+
data = {id: 1}
|
86
|
+
|
87
|
+
converter.stub(call: data)
|
88
|
+
|
89
|
+
expect(subject.result_class).to receive(:new).with(data)
|
90
|
+
|
91
|
+
subject.load(data)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe "#dump" do
|
96
|
+
it "dump the object as a hash" do
|
97
|
+
obj = subject.result_class.new 1, "paul"
|
98
|
+
|
99
|
+
expect(reverse_converter).to receive(:call)
|
100
|
+
|
101
|
+
subject.dump(obj)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Yaoc::Strategies::ToArrayMapping do
|
4
|
+
subject{
|
5
|
+
Struct.new(:to_convert) do
|
6
|
+
include Yaoc::MappingBase
|
7
|
+
include Yaoc::Strategies::ToArrayMapping
|
8
|
+
end
|
9
|
+
}
|
10
|
+
|
11
|
+
let(:mapper){
|
12
|
+
subject.new(source_object)
|
13
|
+
}
|
14
|
+
|
15
|
+
let(:source_object){
|
16
|
+
{id: 1, name: "paul"}
|
17
|
+
}
|
18
|
+
|
19
|
+
let(:expected_array){
|
20
|
+
[1, "paul"]
|
21
|
+
}
|
22
|
+
|
23
|
+
describe ".call" do
|
24
|
+
|
25
|
+
it "creates a hash from a object" do
|
26
|
+
subject.map(0, :id)
|
27
|
+
subject.map(1, :name)
|
28
|
+
|
29
|
+
expect(mapper.call).to eq(expected_array)
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
it "uses my converter proc" do
|
34
|
+
subject.map(0, :id)
|
35
|
+
subject.map(3, :fullname, ->(source, result){ result[3] = "#{source.fetch(:name)} Hello World" })
|
36
|
+
|
37
|
+
ext_expectation = expected_array.clone
|
38
|
+
ext_expectation[3] = "#{ext_expectation[1]} Hello World"
|
39
|
+
ext_expectation[1] = nil
|
40
|
+
ext_expectation[2] = nil
|
41
|
+
|
42
|
+
expect(mapper.call).to eq(ext_expectation)
|
43
|
+
end
|
44
|
+
|
45
|
+
context "changed fetcher method" do
|
46
|
+
let(:source_object){
|
47
|
+
Struct.new(:id, :name).new(1, "paul")
|
48
|
+
}
|
49
|
+
|
50
|
+
it "uses custom fetcher methods" do
|
51
|
+
subject.map(0, :id)
|
52
|
+
subject.map(1, :name)
|
53
|
+
|
54
|
+
def mapper.fetcher
|
55
|
+
:public_send
|
56
|
+
end
|
57
|
+
|
58
|
+
expect(mapper.call).to eq(expected_array)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "works with arrays" do
|
62
|
+
subject.map(1, 0)
|
63
|
+
subject.map(0, 1)
|
64
|
+
|
65
|
+
def mapper.fetcher
|
66
|
+
:[]
|
67
|
+
end
|
68
|
+
|
69
|
+
mapper.to_convert = [1, "paul"]
|
70
|
+
|
71
|
+
expect(mapper.call).to eq(expected_array.reverse)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Yaoc::Strategies::ToHashMapping do
|
4
|
+
subject{
|
5
|
+
Struct.new(:to_convert) do
|
6
|
+
include Yaoc::MappingBase
|
7
|
+
include Yaoc::Strategies::ToHashMapping
|
8
|
+
end
|
9
|
+
}
|
10
|
+
|
11
|
+
let(:mapper){
|
12
|
+
subject.new(source_object)
|
13
|
+
}
|
14
|
+
|
15
|
+
let(:source_object){
|
16
|
+
{id: 1, name: "paul"}
|
17
|
+
}
|
18
|
+
|
19
|
+
let(:expected_hash){
|
20
|
+
{id: 1, name: "paul"}
|
21
|
+
}
|
22
|
+
|
23
|
+
describe ".call" do
|
24
|
+
|
25
|
+
it "creates a hash from a object" do
|
26
|
+
subject.map(:id, :id)
|
27
|
+
subject.map(:name, :name)
|
28
|
+
|
29
|
+
expect(mapper.call).to eq(expected_hash)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "renames attributes" do
|
33
|
+
subject.map(:id, :id)
|
34
|
+
subject.map(:fullname, :name)
|
35
|
+
|
36
|
+
renamed_expectation = expected_hash.clone
|
37
|
+
renamed_expectation[:fullname] = renamed_expectation.delete :name
|
38
|
+
|
39
|
+
expect(mapper.call).to eq(renamed_expectation)
|
40
|
+
end
|
41
|
+
|
42
|
+
it "uses my converter proc" do
|
43
|
+
subject.map(:id, :id)
|
44
|
+
subject.map(:name, :fullname, ->(source, result){ result.merge({name: source.fetch(:name) + " Hello World"}) })
|
45
|
+
|
46
|
+
ext_expectation = expected_hash.clone
|
47
|
+
ext_expectation[:name] += " Hello World"
|
48
|
+
|
49
|
+
expect(mapper.call).to eq(ext_expectation)
|
50
|
+
end
|
51
|
+
|
52
|
+
context "changed fetcher method" do
|
53
|
+
let(:source_object){
|
54
|
+
Struct.new(:id, :name).new(1, "paul")
|
55
|
+
}
|
56
|
+
|
57
|
+
it "uses custom fetcher methods" do
|
58
|
+
subject.map(:id, :id)
|
59
|
+
subject.map(:name, :name)
|
60
|
+
|
61
|
+
def mapper.fetcher
|
62
|
+
:public_send
|
63
|
+
end
|
64
|
+
|
65
|
+
expect(mapper.call).to eq(expected_hash)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "works with arrays" do
|
69
|
+
subject.map(:id, 0)
|
70
|
+
subject.map(:name, 1)
|
71
|
+
|
72
|
+
def mapper.fetcher
|
73
|
+
:[]
|
74
|
+
end
|
75
|
+
|
76
|
+
mapper.to_convert = [1, "paul"]
|
77
|
+
|
78
|
+
expect(mapper.call).to eq(expected_hash)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
data/yaoc.gemspec
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'yaoc/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "yaoc"
|
8
|
+
spec.version = Yaoc::VERSION
|
9
|
+
spec.authors = ["Dieter Späth"]
|
10
|
+
spec.email = ["dieter.spaeth@gmx.de"]
|
11
|
+
spec.summary = %q{Yet another object converter}
|
12
|
+
spec.description = %q{Yet another object converter}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.required_ruby_version = '>= 2.0.0'
|
22
|
+
|
23
|
+
spec.add_runtime_dependency "abstract_type", '~> 0.0.7'
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
26
|
+
spec.add_development_dependency "rake"
|
27
|
+
|
28
|
+
spec.add_development_dependency "rspec", "2.99.0.beta1"
|
29
|
+
# show nicely how many specs have to be run
|
30
|
+
spec.add_development_dependency "fuubar"
|
31
|
+
# extended console
|
32
|
+
spec.add_development_dependency "pry"
|
33
|
+
spec.add_development_dependency 'pry-remote'
|
34
|
+
|
35
|
+
# automatic execute tasks on file changes
|
36
|
+
spec.add_development_dependency 'guard'
|
37
|
+
spec.add_development_dependency 'guard-rspec'
|
38
|
+
spec.add_development_dependency 'guard-bundler'
|
39
|
+
spec.add_development_dependency 'rb-fsevent'
|
40
|
+
|
41
|
+
# https://github.com/pry/pry-stack_explorer
|
42
|
+
spec.add_development_dependency 'pry-stack_explorer'
|
43
|
+
# https://github.com/nixme/pry-debugger
|
44
|
+
spec.add_development_dependency 'pry-debugger'
|
45
|
+
|
46
|
+
# https://github.com/dkubb/equalizer
|
47
|
+
spec.add_development_dependency 'equalizer'
|
48
|
+
end
|
metadata
ADDED
@@ -0,0 +1,267 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: yaoc
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dieter Späth
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-01-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: abstract_type
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.0.7
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.0.7
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.5'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.5'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 2.99.0.beta1
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 2.99.0.beta1
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: fuubar
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: pry-remote
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: guard
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: guard-rspec
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: guard-bundler
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: rb-fsevent
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: pry-stack_explorer
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: pry-debugger
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - ">="
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
- !ruby/object:Gem::Dependency
|
196
|
+
name: equalizer
|
197
|
+
requirement: !ruby/object:Gem::Requirement
|
198
|
+
requirements:
|
199
|
+
- - ">="
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
type: :development
|
203
|
+
prerelease: false
|
204
|
+
version_requirements: !ruby/object:Gem::Requirement
|
205
|
+
requirements:
|
206
|
+
- - ">="
|
207
|
+
- !ruby/object:Gem::Version
|
208
|
+
version: '0'
|
209
|
+
description: Yet another object converter
|
210
|
+
email:
|
211
|
+
- dieter.spaeth@gmx.de
|
212
|
+
executables: []
|
213
|
+
extensions: []
|
214
|
+
extra_rdoc_files: []
|
215
|
+
files:
|
216
|
+
- ".gitignore"
|
217
|
+
- Gemfile
|
218
|
+
- Guardfile
|
219
|
+
- LICENSE.txt
|
220
|
+
- README.md
|
221
|
+
- Rakefile
|
222
|
+
- lib/yaoc.rb
|
223
|
+
- lib/yaoc/mapping_base.rb
|
224
|
+
- lib/yaoc/object_mapper.rb
|
225
|
+
- lib/yaoc/strategies/to_array_mapping.rb
|
226
|
+
- lib/yaoc/strategies/to_hash_mapping.rb
|
227
|
+
- lib/yaoc/version.rb
|
228
|
+
- spec/acceptance/map_objects_spec.rb
|
229
|
+
- spec/spec_helper.rb
|
230
|
+
- spec/support/feature.rb
|
231
|
+
- spec/unit/lib/yaoc/mapping_base_spec.rb
|
232
|
+
- spec/unit/lib/yaoc/object_mapper_spec.rb
|
233
|
+
- spec/unit/lib/yaoc/strategies/to_array_mapping_spec.rb
|
234
|
+
- spec/unit/lib/yaoc/strategies/to_hash_mapping_spec.rb
|
235
|
+
- yaoc.gemspec
|
236
|
+
homepage: ''
|
237
|
+
licenses:
|
238
|
+
- MIT
|
239
|
+
metadata: {}
|
240
|
+
post_install_message:
|
241
|
+
rdoc_options: []
|
242
|
+
require_paths:
|
243
|
+
- lib
|
244
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
245
|
+
requirements:
|
246
|
+
- - ">="
|
247
|
+
- !ruby/object:Gem::Version
|
248
|
+
version: 2.0.0
|
249
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
250
|
+
requirements:
|
251
|
+
- - ">="
|
252
|
+
- !ruby/object:Gem::Version
|
253
|
+
version: '0'
|
254
|
+
requirements: []
|
255
|
+
rubyforge_project:
|
256
|
+
rubygems_version: 2.2.1
|
257
|
+
signing_key:
|
258
|
+
specification_version: 4
|
259
|
+
summary: Yet another object converter
|
260
|
+
test_files:
|
261
|
+
- spec/acceptance/map_objects_spec.rb
|
262
|
+
- spec/spec_helper.rb
|
263
|
+
- spec/support/feature.rb
|
264
|
+
- spec/unit/lib/yaoc/mapping_base_spec.rb
|
265
|
+
- spec/unit/lib/yaoc/object_mapper_spec.rb
|
266
|
+
- spec/unit/lib/yaoc/strategies/to_array_mapping_spec.rb
|
267
|
+
- spec/unit/lib/yaoc/strategies/to_hash_mapping_spec.rb
|