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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cf1c7c828053b75ccd40b4727fc0ab95b85536a1
4
- data.tar.gz: 1de27fffeb496e08ffd418d8e79843196f9c613e
3
+ metadata.gz: f61f54bcd4b19eae357e8b121765aae2437f0db6
4
+ data.tar.gz: 690d5a86cae5781ff21024436a42037093918776
5
5
  SHA512:
6
- metadata.gz: d0ecee7474691679b643c5102089575adef6be95aaca636f8b7f42ca66b8248f77f6fe3a41360e48ead89ec3bf38c8c03f9166860dd7ed1ede77db506c27354c
7
- data.tar.gz: ef4708b9d7922b4211b7322af5f7bf8e936b78f0a92c80025a69cc05ea07cfd203608bf81e7b7eec832290cb89a7d309d0d4d684d2e86e45a9db205866106829
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:
@@ -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: OpenStruct.method(:new),
32
+ target_builder: target_builder,
27
33
  legend: legend
28
34
  ).call(source_instance)
29
35
  end
@@ -14,7 +14,7 @@ module Mappy
14
14
  m[target_attribute] = extract_attribute_for(source, source_method)
15
15
  m
16
16
  end
17
- target_builder.call(attributes)
17
+ target_builder.new(attributes)
18
18
  end
19
19
 
20
20
  protected
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Mappy
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
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: :document, legend: legend)
25
+ subject.legend(source: source_type, target: target_type, legend: legend)
22
26
  end
23
27
  it 'should yield a map storage' do
24
- document = subject.map(article, target: :document)
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) { lambda {|attrs| OpenStruct.new(attrs) } }
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
@@ -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: 'orcid/work',
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
- double('Journal', to_mappy_type: :journal, title: title)
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.1
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