integrated_data 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: feede0b1ad2087f3b7e3402a9ce5fa008fe73581
4
+ data.tar.gz: 37ebb4022498eedcb5e0abab75fc3128fb8f04c7
5
+ SHA512:
6
+ metadata.gz: 8a40a762fecc1a8612a26f58bd0ba236b8fee9263d591762b98c108e939e36bee1358f320873949f6f8738e3abf2ef4b8df83cf1636797b53d7af006e919810f
7
+ data.tar.gz: 1f92981670d5344cd6832dfd7b4a07930bf6c87132690ba6d1f0427ee9aafd6efe76e5d29e1bc673e41daf521cc17ccce35d6c16f57c6d1a8e39706bd0ad71ed
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ .pryrc
16
+ gems
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'pry',
6
+ group: [:development, :test]
7
+
8
+ gem 'simplecov', '>= 0.7.0',
9
+ require: false,
10
+ group: :test
11
+
12
+ gem 'coveralls',
13
+ require: false,
14
+ group: :test
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Chris Keele
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,277 @@
1
+ IntegratedData
2
+ ==============
3
+
4
+ > *A tool for compositing custom domain objects from disparate data sources.*
5
+
6
+
7
+
8
+ Synopsis
9
+ --------
10
+
11
+ `IntegratedData` is a micro-framework for [data integration](http://en.wikipedia.org/wiki/Data_integration) that allows you to build [POROs](http://blog.jayfields.com/2007/10/ruby-poro.html) whose properties are scattered across various sources.
12
+
13
+
14
+
15
+ Concepts
16
+ --------
17
+
18
+
19
+ ### Data Sources
20
+
21
+ An `IntegratedData::Source` is any class capable of retrieving data from some source on initialization. It could access a database, API, CSV, or pretty much anything under the digital sun. Public methods of `IntegratedData::Sources` act like different strategies for accessing the data therein.
22
+
23
+
24
+ ### Entities
25
+
26
+ An `IntegratedData::Entity` represents a concept with various attributes. Each attribute can specify different data sources and strategies it can be derived from, using different identifiers.
27
+
28
+
29
+ ### Identifiers
30
+
31
+ Finally, you are encouraged to make proper value objects for your identifiers by using `IntegratedData::Identifier`s. When initializing an entity, any ids with a corresponding identifier class will be coerced into an instance of one of these.
32
+
33
+
34
+
35
+ API
36
+ ---
37
+
38
+
39
+ ### Data Sources
40
+
41
+ Convert any class into a data source by extending `IntegratedData::Source`:
42
+
43
+ ```ruby
44
+ require 'integrated_data'
45
+
46
+ class MySource
47
+ extend IntegratedData::Source
48
+ end
49
+ ```
50
+
51
+ #### Requirements
52
+
53
+ Sources are required to implement these methods:
54
+
55
+ - *`IntegratedData::Source.build(options = {})`*
56
+
57
+ Data sources must implement a class method, `build`, that can accept a Hash of options and returns an object you can invoke strategies on.
58
+
59
+ - *`IntegratedData::Source` strategies*
60
+
61
+ The object returned by `IntegratedData::Source.build` should have public methods that accept a single argument–an identifier–and return data from the source.
62
+
63
+ #### Results
64
+
65
+ - *Hooked in*
66
+
67
+ When the class is used as the `:source` parameter of the `IntegratedData::Entity.lookup` DSL, it will be used to fetch data for that attribute.
68
+
69
+ #### Extensions
70
+
71
+ There are currently no gems that extend `IntegratedData::Source`.
72
+
73
+
74
+ ### Identifiers
75
+
76
+ Convert any class into an identifier by extending `IntegratedData::Identifier`:
77
+
78
+ ```ruby
79
+ require 'integrated_data'
80
+
81
+ class MyIdentifier
82
+ extend IntegratedData::Identifier
83
+ end
84
+ ```
85
+
86
+ #### Requirements
87
+
88
+ Entities are required to implement these methods:
89
+
90
+ - *`IntegratedData::Identifier#parse(value)`*
91
+
92
+ Identifiers must be able to be parse values into a value object.
93
+
94
+ #### Results
95
+
96
+ - *Hooked in*
97
+
98
+ When the class is used as the `:identifier` parameter of the `IntegratedData::Entity.lookup` DSL, it will be used to coerce identifiers into that value object.
99
+
100
+ #### Extensions
101
+
102
+ There are currently no gems that extend `IntegratedData::Identifier`.
103
+
104
+
105
+ ### Entities
106
+
107
+ Convert any class into an entity by extending `IntegratedData::Entity`:
108
+
109
+ ```ruby
110
+ require 'integrated_data'
111
+
112
+ class MyEntity
113
+ extend IntegratedData::Entity
114
+ end
115
+ ```
116
+
117
+ #### Requirements
118
+
119
+ Entities are required to implement these methods:
120
+
121
+ - *`IntegratedData::Source#initialize(attributes = {})`*
122
+
123
+ Entities must be able to be initialized with a single argument, a Hash of attributes.
124
+
125
+ #### Results
126
+
127
+ - *Lookup DSL*
128
+
129
+ Entities gain a class method, `lookup`, that can be used to register ways to look up attributes. They can be instantiated with a hash of identifiers, and are then automatically initialized with a hash of attributes.
130
+
131
+ - *`@identifiers`*
132
+
133
+ Entity instances have access to an instance variable, `@identifiers`, reflecting the identifiers they were furnished with on initialization.
134
+
135
+ - *`@attributes`*
136
+
137
+ Entity instances have access to an instance variable, `@attributes`, reflecting the attributes they were furnished with on initialization.
138
+
139
+ #### Extensions
140
+
141
+ There are currently no gems that extend `IntegratedData::Entity`.
142
+
143
+
144
+
145
+ Examples
146
+ --------
147
+
148
+
149
+ ### Sources
150
+
151
+ #### CSVs
152
+
153
+ An in-memory data source could be implemented as such:
154
+
155
+ ```ruby
156
+ class InMemorySource < Array
157
+
158
+ # This simply creates a default `build` method that raises an NotImplementedError.
159
+ extend IntegratedData::Source
160
+
161
+ # Here we fulfill the IntegratedData::Source interface
162
+ # by overriding the class method with our own implementation.
163
+ class << self
164
+ # `build` must accept a Hash; in this case we require an array of hashes.
165
+ def build(data: [])
166
+ data = Array.try_convert(data).map do |hashlike|
167
+ Hash.try_convert(data)
168
+ end.compact
169
+ new data
170
+ end
171
+ end
172
+
173
+ # Default strategy, if none is specified by the entity
174
+ def call(id)
175
+ find do |attributes|
176
+ id == attributes[:id]
177
+ end
178
+ end
179
+
180
+ end
181
+ ```
182
+
183
+ A CSV data source could be implemented as such:
184
+
185
+ ```ruby
186
+ require 'smarter_csv'
187
+ class CSVSource
188
+
189
+ # This simply creates a default `build` method that raises an NotImplementedError.
190
+ extend IntegratedData::Source
191
+
192
+ # Here we fulfill the IntegratedData::Source interface
193
+ # by overriding the class method with our own implementation.
194
+ class << self
195
+ # `build` must accept a Hash; in this case we require a file parameter.
196
+ def build(file:)
197
+ new(file)
198
+ end
199
+ end
200
+
201
+ # Just store the file for reference so CSVs are only parsed when needed.
202
+ def initialize(file)
203
+ @file = file
204
+ end
205
+
206
+ # Default strategy, if none is specified by the entity
207
+ def call(id)
208
+ @data ||= SmarterCSV.process(@file)
209
+ @data.find do |attributes|
210
+ id == attributes[:id]
211
+ end
212
+ end
213
+
214
+ # Custom strategy with variant behavior, used on demand.
215
+ # In this case, if an entity needs multiple attributes from the csv file,
216
+ # and it's using the `:uncached` strategy,
217
+ # it'll process the csv each time it needs an attribute from it.
218
+ def uncached(id)
219
+ SmarterCSV.process(@file).find do |attributes|
220
+ id == attributes[:id]
221
+ end
222
+ end
223
+
224
+ end
225
+ ```
226
+
227
+
228
+ ### Identifiers
229
+
230
+ An identifier could be implemented as such:
231
+
232
+ ```ruby
233
+ class PaddedString < String
234
+
235
+ # This simply creates a default `parse` method that raises an NotImplementedError.
236
+ extend IntegratedData::Identifier
237
+
238
+ # Here we fulfill the IntegratedData::Identifier interface
239
+ # by overriding the class method with our own implementation.
240
+ class << self
241
+ # `parse` must accept a single value to be coerced.
242
+ def parse(value)
243
+ string = value.to_s
244
+ string.insert(0, '0') until string.length >= 10
245
+ new string
246
+ end
247
+ end
248
+
249
+ # Pad other strings before comparison.
250
+ def == other
251
+ super self.class.parse other
252
+ end
253
+
254
+ end
255
+ ```
256
+
257
+
258
+ ### Entities
259
+
260
+ Finally, we could put it all together as such:
261
+
262
+ ```ruby
263
+ require 'ostruct'
264
+
265
+ # We use OpenStruct to get an object that can be initialized with a hash of attributes.
266
+ class Student < OpenStruct
267
+
268
+ # This allows you to use the `lookup` DSL and defines `new` to hook into it.
269
+ extend IntegratedData::Entity
270
+
271
+ # The full lookup DSL looks like this:
272
+ # lookup :attribute_name, from: SourceClass, by: :identifier_key, with: (OptionalIdentifierClass or nil), strategy: (:optional_strategy_method or :call), **extra_options_for_source)
273
+
274
+ lookup :first_name, from: InMemorySource, by: :student_id, data: [student_id: '0000000001', first_name: 'Chris']
275
+
276
+ end
277
+ ```
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'pry'
3
+ require 'gem/console'
4
+ require 'rake/testtask'
5
+
6
+ task default: :test
7
+
8
+ Gem::Console.enable
9
+
10
+ Rake::TestTask.new do |t|
11
+ t.libs << 'test'
12
+ t.test_files = Dir['test/**/*_test.rb']
13
+ end
data/bin/rake ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+
5
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
6
+
7
+ require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
8
+
9
+ require 'rake'
10
+ Rake.application.run
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "integrated_data"
7
+ spec.version = '0.0.1'
8
+ spec.authors = ["Chris Keele"]
9
+ spec.email = ["dev@chriskeele.com"]
10
+ spec.summary = "A tool for compositing custom domain objects from disparate data sources."
11
+ # spec.description = %q{TODO: Write a longer description. Optional.}
12
+ spec.homepage = ""
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_runtime_dependency "activesupport", ">= 3"
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.7"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency 'minitest', '>= 5.0'
25
+ spec.add_development_dependency 'gem-console'
26
+ end
@@ -0,0 +1,7 @@
1
+ require 'integrated_data/source'
2
+ require 'integrated_data/identifier'
3
+ require 'integrated_data/entity'
4
+
5
+ module IntegratedData
6
+ class Exception < StandardError; end
7
+ end
@@ -0,0 +1,43 @@
1
+ require 'active_support/core_ext/class/attribute'
2
+
3
+ require 'integrated_data/entity/integrator'
4
+ require 'integrated_data/entity/lookup'
5
+
6
+ module IntegratedData
7
+ module Entity
8
+
9
+ class << self
10
+ def extended base; super
11
+ base.class_attribute :lookups, instance_accessor: false, instance_predicate: false
12
+ base.lookups = Set.new
13
+ end
14
+ end
15
+
16
+ def new(identifiers={})
17
+ attributes = integrated(identifiers).attributes
18
+ super(attributes).tap do |entity|
19
+ entity.class_eval do
20
+ @identifiers = identifiers
21
+ @attributes = attributes
22
+ end
23
+ end
24
+ end
25
+
26
+ def lookup(attribute, id: , identifier: nil, source: , strategy: :call, **options, &extractor)
27
+ self.lookups = lookups.dup.add Lookup.new attribute, id, identifier, source, strategy, extractor, options
28
+ end
29
+
30
+ private
31
+
32
+ def integrated(identifiers)
33
+ Integrator.new(identifiers, available_lookups(identifiers.keys))
34
+ end
35
+
36
+ def available_lookups(identifiers)
37
+ lookups.select do |lookup|
38
+ identifiers.include? lookup.id
39
+ end
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,43 @@
1
+ require 'integrated_data/entity/lookup'
2
+
3
+ module IntegratedData
4
+ module Entity
5
+ Integrator = Struct.new(:identifiers, :lookups)
6
+ class Integrator
7
+
8
+ def initialize(*args)
9
+ @cache = {}
10
+ super
11
+ end
12
+
13
+ def attributes
14
+ Hash[
15
+ lookups.group_by(&:attribute).map do |attribute, lookups|
16
+ [ attribute, find_attribute_for(lookups, attribute) ]
17
+ end
18
+ ]
19
+ end
20
+
21
+ private
22
+
23
+ def perform_lookup(lookup)
24
+ @cache[lookup.cache_keys] ||= lookup.perform(identifiers[lookup.id])
25
+ end
26
+
27
+ def data_for(lookup, attribute)
28
+ if data = perform_lookup(lookup)
29
+ lookup.extract data, attribute
30
+ end
31
+ end
32
+
33
+ def find_attribute_for(lookups, attribute)
34
+ lookups.find do |lookup|
35
+ data_for(lookup, attribute).tap do |data|
36
+ return data if data
37
+ end
38
+ end
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,52 @@
1
+ module IntegratedData
2
+ module Entity
3
+ Lookup = Struct.new(:attribute, :id, :identifier, :source, :strategy, :extractor, :options)
4
+ class Lookup
5
+
6
+ class << self
7
+ def cache_keys
8
+ [:identifier, :source, :strategy, :extractor, :options]
9
+ end
10
+ end
11
+
12
+ def cache_keys
13
+ self.class.cache_keys.map do |key|
14
+ send key
15
+ end
16
+ end
17
+
18
+ def perform(value)
19
+ source.build(options).public_send(strategy, id, prepare(value))
20
+ end
21
+
22
+ def extract(data, attribute)
23
+ if extractor
24
+ extractor.call data, attribute
25
+ else
26
+ default_extractor data, attribute
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ class Error < Exception; end
33
+
34
+ def prepare(value)
35
+ identifier ? identifier.parse(value) : value
36
+ end
37
+
38
+ def default_extractor(data, attribute)
39
+ if data.respond_to? :extract
40
+ data.extract attribute
41
+ elsif data.respond_to? :to_h
42
+ data.to_h[attribute]
43
+ elsif data.respond_to? attribute
44
+ data.public_send attribute
45
+ else
46
+ raise Error, "couldn't extract #{attribute} from #{data.class}"
47
+ end
48
+ end
49
+
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,9 @@
1
+ module IntegratedData
2
+ module Identifier
3
+
4
+ def parse(*_)
5
+ raise NotImplementedError, 'IntegratedData::Identifiers must define `parse`'
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module IntegratedData
2
+ module Source
3
+
4
+ def build(*_)
5
+ raise NotImplementedError, 'IntegratedData::Sources must define `build`'
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,59 @@
1
+ require 'test_helper'
2
+
3
+ class EntityTest < Test
4
+
5
+ def pre; super
6
+ @entity_class_name = :TestEntity
7
+ klass = Class.new do
8
+ extend IntegratedData::Entity
9
+ end
10
+ Object.send :const_set, @entity_class_name, klass
11
+ @entity_class = Object.send :const_get, @entity_class_name
12
+ @entity_settings = [:attribute, source: :source, id: :identifier]
13
+ end
14
+
15
+ def post; super
16
+ Object.send :remove_const, @entity_class_name
17
+ @entity_class_name = nil
18
+ @entity_class = nil
19
+ @entity_settings = nil
20
+ end
21
+
22
+ def test_fetch_defines_new_lookups
23
+ around do
24
+ assert_change ->{ @entity_class.lookups.length } do
25
+ @entity_class.lookup *@entity_settings
26
+ end
27
+ end
28
+ end
29
+
30
+ def test_lookups_without_strategies_dont_repeat
31
+ around do
32
+ @entity_class.lookup *@entity_settings
33
+ refute_change ->{ @entity_class.lookups.length } do
34
+ @entity_class.lookup *@entity_settings
35
+ end
36
+ end
37
+ end
38
+
39
+ def test_lookups_with_strategies_dont_repeat
40
+ around do
41
+ @entity_settings.last[:strategy] = :strategy
42
+ @entity_class.lookup *@entity_settings
43
+ refute_change ->{ @entity_class.lookups.length } do
44
+ @entity_class.lookup *@entity_settings
45
+ end
46
+ end
47
+ end
48
+
49
+ def test_lookups_mixing_strategies_do_repeat
50
+ around do
51
+ @entity_class.lookup *@entity_settings
52
+ assert_change ->{ @entity_class.lookups.length } do
53
+ @entity_settings.last[:strategy] = :strategy
54
+ @entity_class.lookup *@entity_settings
55
+ end
56
+ end
57
+ end
58
+
59
+ end
File without changes
File without changes
@@ -0,0 +1,99 @@
1
+ require 'test_helper'
2
+
3
+ class Rxcui < String
4
+
5
+ extend IntegratedData::Identifier
6
+
7
+ class << self
8
+ def parse(input)
9
+ new input.to_s
10
+ end
11
+ end
12
+
13
+ def == other
14
+ super self.class.parse other
15
+ end
16
+
17
+ end
18
+
19
+ class RxNorm
20
+
21
+ extend IntegratedData::Source
22
+
23
+ class << self
24
+ alias_method :build, :new
25
+ end
26
+
27
+ def initialize(data: )
28
+ @data = data
29
+ end
30
+
31
+ def method_missing(method, id, value)
32
+ @data[method == :call ? :default : method].find do |datum|
33
+ value == datum[id]
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ require 'ostruct'
40
+ class Drug < OpenStruct
41
+
42
+ extend IntegratedData::Entity
43
+
44
+ class << self
45
+ def data
46
+ {
47
+ default: [
48
+ {
49
+ rxcui: 1,
50
+ name: 'name1',
51
+ extra_name: 'extraname1'
52
+ },
53
+ {
54
+ rxcui: 2,
55
+ name: 'name2',
56
+ extra_name: 'extraname2'
57
+ },
58
+ ],
59
+ custom: [
60
+ {
61
+ rxcui: 1,
62
+ other_name: 'othername1',
63
+ extra_name: 'extraname1'
64
+ },
65
+ {
66
+ rxcui: 2,
67
+ other_name: 'othername2',
68
+ extra_name: 'extraname2'
69
+ },
70
+ ],
71
+ }
72
+ end
73
+ end
74
+
75
+ lookup :name, source: RxNorm, id: :rxcui, identifier: Rxcui, data: data
76
+
77
+ lookup :other_name, source: RxNorm, id: :rxcui, identifier: Rxcui, strategy: :custom, data: data
78
+
79
+ lookup :extra_name, source: RxNorm, id: :rxcui, identifier: Rxcui, data: data do |data, attribute|
80
+ data[attribute]
81
+ end
82
+
83
+ end
84
+
85
+ class IntegratedDataTest < Test
86
+
87
+ def test_default_strategy
88
+ assert_equal 'name1', Drug.new(rxcui: 1).name
89
+ end
90
+
91
+ def test_custom_strategy
92
+ assert_equal 'othername1', Drug.new(rxcui: 1).other_name
93
+ end
94
+
95
+ def test_custom_extractor
96
+ assert_equal 'extraname1', Drug.new(rxcui: 1).extra_name
97
+ end
98
+
99
+ end
@@ -0,0 +1,52 @@
1
+ require 'rubygems'
2
+ require 'pry'
3
+
4
+ begin
5
+ require 'simplecov'
6
+ SimpleCov.coverage_dir 'coverage'
7
+ if ENV['CI'] and require 'coveralls'
8
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
9
+ SimpleCov::Formatter::HTMLFormatter,
10
+ Coveralls::SimpleCov::Formatter
11
+ ]
12
+ end
13
+ SimpleCov.start do
14
+ add_filter "/test"
15
+ end
16
+ end
17
+
18
+ require 'minitest/autorun'
19
+
20
+ class Test < MiniTest::Test
21
+
22
+ def assert_change(lambda_getter)
23
+ old = lambda_getter.call
24
+ yield
25
+ refute_equal old, lambda_getter.call, "Expected block to change output of lambda argument"
26
+ end
27
+
28
+ def refute_change(lambda_getter)
29
+ old = lambda_getter.call
30
+ yield
31
+ assert_equal old, lambda_getter.call, "Didn't expect block to change output of lambda argument"
32
+ end
33
+
34
+ def setup; end
35
+ def teardown; end
36
+
37
+ class Namespace; end
38
+
39
+ def around
40
+ pre
41
+ yield
42
+ post
43
+ end
44
+
45
+ def pre; end
46
+ def post; end
47
+
48
+ end
49
+
50
+ require 'integrated_data'
51
+
52
+ puts 'Running tests...'
metadata ADDED
@@ -0,0 +1,138 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: integrated_data
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Chris Keele
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-07-23 00:00:00.000000000 Z
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: '3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '3'
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.7'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.7'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '5.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '5.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: gem-console
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
+ description:
84
+ email:
85
+ - dev@chriskeele.com
86
+ executables:
87
+ - rake
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - Gemfile
93
+ - LICENSE.txt
94
+ - README.md
95
+ - Rakefile
96
+ - bin/rake
97
+ - integrated_data.gemspec
98
+ - lib/integrated_data.rb
99
+ - lib/integrated_data/entity.rb
100
+ - lib/integrated_data/entity/integrator.rb
101
+ - lib/integrated_data/entity/lookup.rb
102
+ - lib/integrated_data/identifier.rb
103
+ - lib/integrated_data/source.rb
104
+ - test/integrated_data/entity_test.rb
105
+ - test/integrated_data/identifier_test.rb
106
+ - test/integrated_data/source_test.rb
107
+ - test/integrated_data_test.rb
108
+ - test/test_helper.rb
109
+ homepage: ''
110
+ licenses:
111
+ - MIT
112
+ metadata: {}
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project:
129
+ rubygems_version: 2.2.2
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: A tool for compositing custom domain objects from disparate data sources.
133
+ test_files:
134
+ - test/integrated_data/entity_test.rb
135
+ - test/integrated_data/identifier_test.rb
136
+ - test/integrated_data/source_test.rb
137
+ - test/integrated_data_test.rb
138
+ - test/test_helper.rb