integrated_data 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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