mappy 0.0.1 → 0.0.2

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