mappy 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +15 -0
- data/lib/mappy/configuration.rb +7 -1
- data/lib/mappy/resolver.rb +1 -1
- data/lib/mappy/target_builder_factory.rb +37 -0
- data/lib/mappy/version.rb +1 -1
- data/mappy.gemspec +1 -0
- data/spec/lib/mappy/configuration_spec.rb +8 -2
- data/spec/lib/mappy/resolver_spec.rb +1 -1
- data/spec/lib/mappy/target_builder_factory_spec.rb +27 -0
- data/spec/lib/mappy_spec.rb +4 -6
- data/spec/lib/model_support.rb +14 -0
- metadata +20 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f61f54bcd4b19eae357e8b121765aae2437f0db6
|
4
|
+
data.tar.gz: 690d5a86cae5781ff21024436a42037093918776
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6a366fa8161a24d3eec2da41bf226ad55bd83b47b1e32fc2295a18aef024121b110f4c38156711ee9ea4c5c0e42c8ff61b9652280e0c6c7e055b8aa7c071c9f2
|
7
|
+
data.tar.gz: dd9e93aa43fcc49d43d9be06c831783b912537bf63d0c3a1fc321028ef9f6f55c337c4f795f92a4641dbbc74f97654a72ccfcc2bf09b539955d9fc993d2e3f43
|
data/README.md
CHANGED
@@ -3,6 +3,21 @@
|
|
3
3
|
Map one object to another. Apsiring to be a DSL for mapping one object's "data
|
4
4
|
structure" onto another object's "data structure".
|
5
5
|
|
6
|
+
## Why?
|
7
|
+
|
8
|
+
Because I have discovered that I am regularly working with a heterogenious set of
|
9
|
+
objects that need to be handled via some other service. And that service has its
|
10
|
+
expected data structure. And there are quite a few services.
|
11
|
+
|
12
|
+
That is to say, I'm attempting to submit a work to my Orcid Profile. I need some
|
13
|
+
method for defining how to map my home grown "Article" object to the attributes
|
14
|
+
that are needed for an Orcide work. And I don't want to infect my Article class
|
15
|
+
with a #to_orcid_profile_attributes method.
|
16
|
+
|
17
|
+
Or I want to create a DOI for my Article.
|
18
|
+
|
19
|
+
In essence, Mappy provides a configurable seam in an application.
|
20
|
+
|
6
21
|
## Installation
|
7
22
|
|
8
23
|
Add this line to your application's Gemfile:
|
data/lib/mappy/configuration.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require "mappy/resolver"
|
2
|
+
require "mappy/target_builder_factory"
|
3
|
+
|
1
4
|
module Mappy
|
2
5
|
|
3
6
|
class Configuration
|
@@ -18,12 +21,15 @@ module Mappy
|
|
18
21
|
def map(source_instance, options = {})
|
19
22
|
source = source_instance.to_mappy_type
|
20
23
|
target = options.fetch(:target)
|
24
|
+
target_builder_finder = options.fetch(:target_builder_finder) { Mappy::TargetBuilderFactory }
|
21
25
|
legend = map_store.fetch(target).fetch(source)
|
22
26
|
|
27
|
+
target_builder = target_builder_finder.call(target)
|
28
|
+
|
23
29
|
# @Todo: The returned value should not be an OpenStruct, but should
|
24
30
|
# be an instance of the target (as per some Mappy resolver).
|
25
31
|
Resolver.new(
|
26
|
-
target_builder:
|
32
|
+
target_builder: target_builder,
|
27
33
|
legend: legend
|
28
34
|
).call(source_instance)
|
29
35
|
end
|
data/lib/mappy/resolver.rb
CHANGED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'active_support/inflector'
|
2
|
+
|
3
|
+
module Mappy
|
4
|
+
class InvalidTargetBuilder < RuntimeError
|
5
|
+
end
|
6
|
+
|
7
|
+
# Responsible for taking a symbol, finding the appropriate class then
|
8
|
+
# verifying that the class is "well formed."
|
9
|
+
class TargetBuilderFactory
|
10
|
+
|
11
|
+
def self.call(*args)
|
12
|
+
new.call(*args)
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(target_symbol)
|
16
|
+
target_builder = extract_target_builder(target_symbol)
|
17
|
+
validate!(target_builder)
|
18
|
+
target_builder
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def extract_target_builder(target_symbol)
|
23
|
+
target_symbol.to_s.classify.constantize
|
24
|
+
end
|
25
|
+
|
26
|
+
def validate!(target_builder)
|
27
|
+
target_instance = target_builder.allocate
|
28
|
+
|
29
|
+
begin
|
30
|
+
target_instance.send(:initialize, {})
|
31
|
+
rescue ArgumentError => e
|
32
|
+
raise InvalidTargetBuilder.new("Expected #{target_builder} to initialize with an attributes hash.\n#{e}")
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/mappy/version.rb
CHANGED
data/mappy.gemspec
CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
+
spec.add_dependency 'activesupport'
|
21
22
|
spec.add_development_dependency "bundler", "~> 1.5"
|
22
23
|
spec.add_development_dependency "rake"
|
23
24
|
spec.add_development_dependency "rspec"
|
@@ -17,11 +17,17 @@ module Mappy
|
|
17
17
|
context '#map' do
|
18
18
|
let(:source_type) {:article}
|
19
19
|
let(:article) { double('Article', title: 'Hello', to_mappy_type: source_type) }
|
20
|
+
let(:target_builder) { OpenStruct }
|
21
|
+
let(:target_type) { :document }
|
22
|
+
let(:target_builder_finder) { double("Finder") }
|
23
|
+
|
20
24
|
before(:each) do
|
21
|
-
subject.legend(source: source_type, target:
|
25
|
+
subject.legend(source: source_type, target: target_type, legend: legend)
|
22
26
|
end
|
23
27
|
it 'should yield a map storage' do
|
24
|
-
|
28
|
+
target_builder_finder.should_receive(:call).with(target_type).and_return(target_builder)
|
29
|
+
|
30
|
+
document = subject.map(article, target: target_type, target_builder_finder: target_builder_finder)
|
25
31
|
expect(document.title).to eq(article.title)
|
26
32
|
end
|
27
33
|
end
|
@@ -5,7 +5,7 @@ module Mappy
|
|
5
5
|
describe Resolver do
|
6
6
|
let(:source_publisher) { lambda {|source| source.publishers.join("; ")}}
|
7
7
|
let(:source) { double('Source', title: 'A Title', publishers: ["John", "Ringo"]) }
|
8
|
-
let(:target_builder) {
|
8
|
+
let(:target_builder) { OpenStruct }
|
9
9
|
let(:legend) {
|
10
10
|
[
|
11
11
|
[:title, :title],
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.expand_path('../../../../lib/mappy/target_builder_factory', __FILE__)
|
2
|
+
require File.expand_path('../../model_support', __FILE__)
|
3
|
+
|
4
|
+
module Mappy
|
5
|
+
describe TargetBuilderFactory do
|
6
|
+
subject { described_class.new }
|
7
|
+
|
8
|
+
context '.call' do
|
9
|
+
it 'returns a builder lambda based on the input' do
|
10
|
+
expect(described_class.call('mappy/mock_valid_model')).to respond_to(:new)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context '#call' do
|
15
|
+
it 'returns a builder lambda based on the input' do
|
16
|
+
expect(subject.call('mappy/mock_valid_model')).to respond_to(:new)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'raises an exception when the builder does not have attributes' do
|
20
|
+
expect {
|
21
|
+
subject.call('mappy/mock_invalid_model')
|
22
|
+
}.to raise_error
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/spec/lib/mappy_spec.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require File.expand_path('../../../lib/mappy', __FILE__)
|
2
|
+
require File.expand_path('../model_support', __FILE__)
|
2
3
|
|
3
4
|
describe Mappy do
|
4
5
|
context '.to_type' do
|
@@ -14,7 +15,7 @@ describe Mappy do
|
|
14
15
|
Mappy.configure do |config|
|
15
16
|
config.legend(
|
16
17
|
source: :journal,
|
17
|
-
target: '
|
18
|
+
target: 'mappy/mock_valid_model',
|
18
19
|
legend: [
|
19
20
|
[:title, :title],
|
20
21
|
[lambda{|*|'long-journal'}, :work_type],
|
@@ -27,11 +28,8 @@ describe Mappy do
|
|
27
28
|
end
|
28
29
|
|
29
30
|
let(:title) { 'A Rocking Title' }
|
30
|
-
let(:journal) {
|
31
|
-
|
32
|
-
}
|
33
|
-
|
34
|
-
subject { Mappy.map(journal, target: 'orcid/work') }
|
31
|
+
let(:journal) { double('Journal', to_mappy_type: :journal, title: title) }
|
32
|
+
subject { Mappy.map(journal, target: 'mappy/mock_valid_model') }
|
35
33
|
|
36
34
|
its(:work_type) { should eq('long-journal')}
|
37
35
|
its(:title) { should eq(title) }
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Mappy
|
2
|
+
class MockValidModel
|
3
|
+
attr_accessor :title, :work_type
|
4
|
+
def initialize(attributes)
|
5
|
+
attributes.each_pair do |key, value|
|
6
|
+
send("#{key}=", value) if respond_to?("#{key}=")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class MockInvalidModel
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mappy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Friesen
|
@@ -10,6 +10,20 @@ bindir: bin
|
|
10
10
|
cert_chain: []
|
11
11
|
date: 2014-02-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -82,11 +96,14 @@ files:
|
|
82
96
|
- lib/mappy.rb
|
83
97
|
- lib/mappy/configuration.rb
|
84
98
|
- lib/mappy/resolver.rb
|
99
|
+
- lib/mappy/target_builder_factory.rb
|
85
100
|
- lib/mappy/version.rb
|
86
101
|
- mappy.gemspec
|
87
102
|
- spec/lib/mappy/configuration_spec.rb
|
88
103
|
- spec/lib/mappy/resolver_spec.rb
|
104
|
+
- spec/lib/mappy/target_builder_factory_spec.rb
|
89
105
|
- spec/lib/mappy_spec.rb
|
106
|
+
- spec/lib/model_support.rb
|
90
107
|
homepage: https://github.com/jeremyf/mappy
|
91
108
|
licenses:
|
92
109
|
- APACHE2
|
@@ -114,4 +131,6 @@ summary: Map one object to another
|
|
114
131
|
test_files:
|
115
132
|
- spec/lib/mappy/configuration_spec.rb
|
116
133
|
- spec/lib/mappy/resolver_spec.rb
|
134
|
+
- spec/lib/mappy/target_builder_factory_spec.rb
|
117
135
|
- spec/lib/mappy_spec.rb
|
136
|
+
- spec/lib/model_support.rb
|