data-provider 0.1.0

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: 38f6f8ba1418886f65eb5bed06cfba596744dfb8
4
+ data.tar.gz: 33d309c91f3cbb341159b20f99129d0ea387a10e
5
+ SHA512:
6
+ metadata.gz: f73b0708c03917f4a58a14bffddbd1357336154b917f0ff610511c0572fb743f12f2824647b36d7bd30972967cc41d6a887de8ae696b6318acd69236a847ec51
7
+ data.tar.gz: a19b6508e5c30fe4ad94ee42c0f205f8a539cc9f1311b9828feb407daf66ab99d2651f8268b418ffaf91c922c93006cfc9a03535a7ee14af676b7382ecc76c13
data/.gitignore ADDED
@@ -0,0 +1,35 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /test/tmp/
9
+ /test/version_tmp/
10
+ /tmp/
11
+
12
+ ## Specific to RubyMotion:
13
+ .dat*
14
+ .repl_history
15
+ build/
16
+
17
+ ## Documentation cache and generated files:
18
+ /.yardoc/
19
+ /_yardoc/
20
+ /doc/
21
+ /rdoc/
22
+
23
+ ## Environment normalisation:
24
+ /.bundle/
25
+ /vendor/bundle
26
+ /lib/bundler/man/
27
+
28
+ # for a library or gem, you might want to ignore these files since the code is
29
+ # intended to run in multiple environments; otherwise, check them in:
30
+ # Gemfile.lock
31
+ .ruby-version
32
+ .ruby-gemset
33
+
34
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
35
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'byebug'
7
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,36 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ data-provider (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ byebug (5.0.0)
10
+ columnize (= 0.9.0)
11
+ columnize (0.9.0)
12
+ diff-lcs (1.2.5)
13
+ rspec (3.3.0)
14
+ rspec-core (~> 3.3.0)
15
+ rspec-expectations (~> 3.3.0)
16
+ rspec-mocks (~> 3.3.0)
17
+ rspec-core (3.3.1)
18
+ rspec-support (~> 3.3.0)
19
+ rspec-expectations (3.3.0)
20
+ diff-lcs (>= 1.2.0, < 2.0)
21
+ rspec-support (~> 3.3.0)
22
+ rspec-mocks (3.3.1)
23
+ diff-lcs (>= 1.2.0, < 2.0)
24
+ rspec-support (~> 3.3.0)
25
+ rspec-support (3.3.0)
26
+
27
+ PLATFORMS
28
+ ruby
29
+
30
+ DEPENDENCIES
31
+ byebug
32
+ data-provider!
33
+ rspec
34
+
35
+ BUNDLED WITH
36
+ 1.10.5
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Mark
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/README.md ADDED
@@ -0,0 +1,154 @@
1
+ # data-provider
2
+ Ruby gem that provides a set of classes to build consistent data interfaces
3
+
4
+ ## Installation
5
+
6
+ Rubygems:
7
+ ```
8
+ gem install data-provider
9
+ ```
10
+
11
+ Bundler:
12
+ ```ruby
13
+ gem 'data-provider'
14
+ ```
15
+
16
+ ## Examples
17
+
18
+ Define a provider class with some providers
19
+ ```ruby
20
+
21
+ require 'data_provider'
22
+
23
+ class BookProvider
24
+ include DataProvider::Base
25
+
26
+ # quick syntax for 'simple' providers
27
+ provides({
28
+ title: 'The Monkey Wrench Gang',
29
+ author: 'Edward Abbey'
30
+ })
31
+
32
+ # longer syntax for more complicated providers
33
+ provider :display_title do
34
+ "#{take(:author)} - #{take(:title)}"
35
+ end
36
+
37
+ provider :price do
38
+ 9.99
39
+ end
40
+ end
41
+ ```
42
+
43
+ Using a provider class
44
+ ```ruby
45
+ book_provider = BookProvider.new()
46
+ book_provider.take(:title) # => 'The Monkey Wrench Gang'
47
+ book_provider.take(:author) # => 'Edward Abbey'
48
+ book_provider.take(:display_title) # => 'Edward Abbey - The Monkey Wrench Gang'
49
+ book_provider.take(:price) # => 9.99
50
+ ```
51
+
52
+ Data providers can be given data to customize their output
53
+ ```ruby
54
+ require 'data_provider'
55
+
56
+ class ProductProvider
57
+ include DataProvider::Base
58
+
59
+ provider :normal_price do
60
+ 17.99
61
+ end
62
+
63
+ provider :discount_price do
64
+ take(:normal_price) - get_data(:discount)
65
+ end
66
+ end
67
+
68
+ product_provider = ProductProvider.new
69
+ product_provider.take(:normal_price) # => 17.99
70
+ product_provider.take(:discount_price) # => TypeError (discount data not given,): nil can't be coerced into Float
71
+ discounted_provider = product_provider.add_data(discount: 3.0) # returns a new instance of the same provider class
72
+ discounted_provider.take(:discount_price) # => 14.99
73
+ product_provider.take(:discount_price) # => TypeError (this instance didn't get the new data)
74
+ product_provider.add_date!(discount: 2) # => Updates this instance instead of creating a new one
75
+ product_provider.take(:discount_price) # => 15.99
76
+ product_provider.add_date!(discount: 4).take(:discount_price) #=> 13.99
77
+ ```
78
+
79
+ Providers can be defined in a module and added to a provider class using the add class-method (not using include!)
80
+ ```ruby
81
+ require 'data-provider'
82
+
83
+ module BandInfo
84
+ include DataProvider::Base
85
+
86
+ provider :band do
87
+ 'D4'
88
+ end
89
+
90
+ provider :bassPlayer do
91
+ 'Paddy'
92
+ end
93
+ end
94
+
95
+ class Band
96
+ include DataProvider::Base
97
+
98
+ provider :band do
99
+ 'Dillinger Four'
100
+ end
101
+
102
+ provider :drummer do
103
+ 'Lane Pederson'
104
+ end
105
+
106
+ add BandInfo # note: add, not include!
107
+ end
108
+
109
+ band = Band.new
110
+ band.take(:band) # => 'D4', class provider was overwritten when the module got added
111
+ band.take(:bassPlayer) # => 'Paddy'
112
+ band.take(:drummer) #=> 'Lane Pederson'
113
+ ```
114
+
115
+ Provider identifiers don't have to be symbols, they can be anything. Specifically array identifiers are suitable for creating data providers for hierarchical systems
116
+ ```ruby
117
+ require 'data_provider'
118
+
119
+ module AlbumProvider
120
+ include DataProvider::Base
121
+
122
+ provides({
123
+ title: 'Reinventing Axle Rose',
124
+ band: 'Against Me!'
125
+ [:band, :hometown] => 'Gainesville, FL'
126
+ })
127
+ end
128
+
129
+ class Catalog
130
+ include DataProvider::Base
131
+
132
+ provider [:music, :album, :bandname] do
133
+ # scoped_take is a method only available inside provider blocks,
134
+ # it lets a provider access other providers in the same 'scope',
135
+ # which means provider whose array-identifiers start with the same values,
136
+ # in this case the scope is [:music, :album]
137
+ scoped_take(:band).upcase
138
+ end
139
+
140
+ # by using `add_scoped` all providers of the added module, will be
141
+ # turned into array and prefixed with the given scope
142
+ add_scoped AlbumProvider, :scope => [:music, :album]
143
+ end
144
+
145
+ catalog = Catalog.new
146
+ catalog.take(:title) # => DataProvider::ProviderMissingException
147
+ catalog.take([:music, :album, :title]) # => 'Reinventing Axle Rose'
148
+ catalog.take([:music, :album, :band, :hometown]) # => 'Gainesville, FL'
149
+ catalog.take([:music, :album, :bandname]) # => 'AGAINST ME!"
150
+ ```
151
+
152
+
153
+
154
+
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ # rxsd project Rakefile
2
+ #
3
+ # Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
4
+ # Licensed under the LGPLv3+ http://www.gnu.org/licenses/lgpl.txt
5
+
6
+ require 'rdoc/task'
7
+ require "rspec/core/rake_task"
8
+
9
+ task :default => :rspec do; end
10
+
11
+ desc "Run all specs"
12
+ RSpec::Core::RakeTask.new('rspec') do |t|
13
+ t.pattern = 'spec/**/*_spec.rb'
14
+ end
15
+
16
+ Rake::RDocTask.new do |rd|
17
+ rd.main = "README.rdoc"
18
+ rd.rdoc_dir = "doc/site/api"
19
+ rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
20
+ end
@@ -0,0 +1,19 @@
1
+ GEM_NAME="data-provider"
2
+ PKG_VERSION='0.1.0'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = GEM_NAME
6
+ s.version = PKG_VERSION
7
+ s.files = `git ls-files`.split($/)
8
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
9
+
10
+ s.add_development_dependency 'rspec'
11
+
12
+ s.author = "Mark van de Korput"
13
+ s.email = "dr.theman@gmail.com"
14
+ s.date = '2015-07-14'
15
+ s.description = %q{A library of Ruby classes to help create consistent data interfaces}
16
+ s.summary = %q{A library of Ruby classes to help create consistent data interfaces}
17
+ s.homepage = %q{https://github.com/markkorput/data-provider}
18
+ s.license = "MIT"
19
+ end
@@ -0,0 +1,227 @@
1
+ require 'logger'
2
+
3
+ module DataProvider
4
+
5
+ class ProviderMissingException < Exception
6
+ end
7
+
8
+ module Base
9
+
10
+ def self.included(base)
11
+ base.class_eval do
12
+ include InstanceMethods
13
+ extend ClassMethods
14
+ end
15
+ end
16
+
17
+ module ClassMethods
18
+ # provides, when called with a hash param, will define 'simple providers' (providers
19
+ # with a simple, static value). When called without a param (or nil) it returns
20
+ # the current cumulative 'simple providers' hash
21
+ def provides simple_provides = nil
22
+ if simple_provides
23
+ @data_provider ||= {}
24
+ @data_provider[:provides] ||= {}
25
+ @data_provider[:provides].merge!(simple_provides)
26
+ return self
27
+ end
28
+ # no data given? just return existing hash
29
+ (@data_provider || {})[:provides] || {}
30
+ end
31
+
32
+ # returns the requested provider as a Provider object
33
+ def get_provider(id)
34
+ args = data_provider_definitions.find{|args| args.first == id}
35
+ return args.nil? ? nil : Provider.new(*args)
36
+ end
37
+
38
+ def provider_identifiers
39
+ (provides.keys + data_provider_definitions.map(&:first)).compact.uniq
40
+ end
41
+
42
+ # adds a new provider to the class
43
+ def provider identifier, opts = {}, &block
44
+ add_provider(identifier, opts, block_given? ? block : nil)
45
+ end
46
+
47
+ # reader method for the raw data of the currently defined providers
48
+ def data_provider_definitions
49
+ ((@data_provider || {})[:provider_args] || [])
50
+ end
51
+
52
+ # returns wether a provider with the given identifier is available
53
+ def has_provider?(identifier)
54
+ (provides[identifier] || get_provider(identifier)) != nil
55
+ end
56
+
57
+ def has_providers_with_scope?(args)
58
+ scope = args.is_a?(Array) ? args : [args]
59
+ provider_identifiers.find{|id| id.is_a?(Array) && id.length > scope.length && id[0..(scope.length-1)] == scope} != nil
60
+ end
61
+
62
+ def fallback_provider?
63
+ !fallback_provider.nil?
64
+ end
65
+
66
+ # adds all the providers defined in the given module to this class
67
+ def add(providers_module)
68
+ data = providers_module.instance_variable_get('@data_provider') || {}
69
+
70
+ (data[:provider_args] || []).each do |definition|
71
+ add_provider(*definition)
72
+ end
73
+
74
+ self.provides(data[:provides] || {})
75
+ end
76
+
77
+ # adds all the providers defined in the given module to this class,
78
+ # but turns their identifiers into array and prefixes the array with the :scope option
79
+ def add_scoped(providers_module, _options = {})
80
+ data = providers_module.instance_variable_get('@data_provider') || {}
81
+
82
+ (data[:provider_args] || []).each do |definition|
83
+ definition[0] = [definition[0]].flatten
84
+ definition[0] = [_options[:scope]].flatten.compact + definition[0] if _options[:scope]
85
+ add_provider(*definition)
86
+ end
87
+
88
+ (data[:provides] || {}).each_pair do |key, value|
89
+ provides(([_options[:scope]].flatten.compact + [key].flatten.compact) => value)
90
+ end
91
+ end
92
+
93
+ def provider_missing &block
94
+ raise "DataProvider::Base#provider_missing expects a block as an argument" if !block_given?
95
+ @data_provider ||= {}
96
+ @data_provider[:provider_missing] = block
97
+ end
98
+
99
+ def fallback_provider
100
+ block = (@data_provider || {})[:provider_missing]
101
+ block.nil? ? nil : Provider.new(nil, nil, block)
102
+ end
103
+
104
+ private
105
+
106
+ def add_provider(identifier, opts = {}, block = nil)
107
+ @data_provider ||= {}
108
+ @data_provider[:provider_args] ||= []
109
+ @data_provider[:provider_args].unshift [identifier, opts, block]
110
+ end
111
+ end # module ClassMethods
112
+
113
+
114
+ module InstanceMethods
115
+
116
+ attr_reader :data
117
+ attr_reader :options
118
+
119
+ def initialize(opts = {})
120
+ @options = opts.is_a?(Hash) ? opts : {}
121
+ @data = options[:data].is_a?(Hash) ? options[:data] : {}
122
+ end
123
+
124
+ def logger
125
+ @logger ||= options[:logger] || Logger.new(STDOUT)
126
+ end
127
+
128
+ def has_provider?(id)
129
+ self.class.has_provider?(id)
130
+ end
131
+
132
+ def has_providers_with_scope?(scope)
133
+ self.class.has_providers_with_scope?(scope)
134
+ end
135
+
136
+ def fallback_provider?
137
+ self.class.fallback_provider?
138
+ end
139
+
140
+ def take(id)
141
+ # first try the simple providers
142
+ if self.class.provides.has_key?(id)
143
+ provider = self.class.provides[id]
144
+ return provider.is_a?(Proc) ? provider.call : provider
145
+ end
146
+ # try to get a provider object
147
+ provider = self.class.get_provider(id)
148
+ if provider
149
+ @scope ||= []
150
+ @scope << (id.is_a?(Array) ? id[0..-2] : [])
151
+ result = instance_eval(&provider.block)
152
+ @scope.pop
153
+ # execute provider object's block within the scope of self
154
+ return result
155
+ end
156
+
157
+ # couldn't find requested provider, let's see if there's a fallback
158
+ if provider = self.class.fallback_provider
159
+ # temporarily set the @missing_provider instance variable, so the
160
+ # fallback provider can use it through the missing_provider private method
161
+ @missing_provider = id
162
+ @scope ||= []
163
+ @scope << (id.is_a?(Array) ? id[0..-2] : [])
164
+ result = instance_eval(&provider.block) # provider.block.call # with the block.call method the provider can't access private methods like missing_provider
165
+ @scope = nil
166
+ return result
167
+ end
168
+ # no fallback either? Time for an error
169
+ raise ProviderMissingException.new(:message=>"Tried to take data from missing provider.", :provider_id => id)
170
+ end
171
+
172
+ def try_take(id, opts = {})
173
+ return take(id) if self.has_provider?(id) || self.fallback_provider?
174
+ if opts[:fallback] == true
175
+
176
+ logger.debug "Try for missing provider: #{id.inspect}"
177
+ return nil
178
+ end
179
+ end
180
+
181
+ private
182
+
183
+ def scoped_take(id)
184
+ take(((@scope || []).last || []) + [id].flatten)
185
+ end
186
+
187
+ public
188
+
189
+ def given(param_name)
190
+ return data[param_name] if data.has_key?(param_name)
191
+ logger.error "Data provider expected missing data with identifier: #{param_name.inspect}"
192
+ # TODO: raise?
193
+ return nil
194
+ end
195
+
196
+ alias :get_data :given
197
+
198
+ def give(_data = {})
199
+ return self.class.new(options.merge(:data => data.merge(_data)))
200
+ end
201
+
202
+ alias :add_scope :give
203
+ alias :add_data :give
204
+
205
+ def give!(_data = {})
206
+ @data = data.merge(_data)
207
+ return self
208
+ end
209
+
210
+ alias :add_scope! :give!
211
+ alias :add_data! :give!
212
+
213
+ private
214
+
215
+ def missing_provider
216
+ # byebug
217
+ @missing_provider
218
+ end
219
+
220
+ def scope
221
+ @scope || []
222
+ end
223
+ end # module InstanceMethods
224
+
225
+ end # module Base
226
+
227
+ end # module DataProvider
@@ -0,0 +1,20 @@
1
+ module DataProvider
2
+ class Provider
3
+ attr_reader :options
4
+ attr_reader :identifier
5
+ attr_reader :block
6
+
7
+ def initialize(identifier, opts = {}, block = nil)
8
+ @identifier = identifier
9
+ @options = opts.is_a?(Hash) ? opts : {}
10
+ @block = block || Proc.new
11
+ end
12
+
13
+ alias_method :id, :identifier
14
+
15
+ def requirements
16
+ [options[:requires]].flatten.compact
17
+ end
18
+
19
+ end # module Provider
20
+ end # module DataProvider
@@ -0,0 +1,2 @@
1
+ require 'data_provider/provider'
2
+ require 'data_provider/base'
@@ -0,0 +1,420 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe DataProvider::Base do
4
+ # Example implementation of DataProvider::Base
5
+ class ProviderClass
6
+ include DataProvider::Base
7
+
8
+ provider :sum, :requires => [:array] do
9
+ sum = 0
10
+
11
+ given(:array).each do |number|
12
+ sum += number.to_i
13
+ end
14
+
15
+ sum
16
+ end
17
+
18
+ provider :static do
19
+ 'StaticValue'
20
+ end
21
+
22
+ provider :billy do
23
+ take([:identification, :fullname])
24
+ end
25
+
26
+ provider [:identification, :firstname] do
27
+ 'Billy'
28
+ end
29
+
30
+ provider [:identification, :lastname] do
31
+ 'Bragg'
32
+ end
33
+
34
+ provider [:identification, :fullname] do
35
+ "#{scoped_take(:firstname)} #{scoped_take(:lastname)}"
36
+ end
37
+ end
38
+
39
+ let(:provider){
40
+ ProviderClass.new(:data => {:array => [1,2,4]})
41
+ }
42
+
43
+ describe "#has_provider?" do
44
+ it 'provides the has_provider? instance method' do
45
+ expect(provider.has_provider?(:sum)).to be true
46
+ expect(provider.has_provider?(:static)).to be true
47
+ expect(provider.has_provider?(:modulus)).to be false
48
+ end
49
+
50
+ it 'provides the has_provider? class method' do
51
+ expect(ProviderClass.respond_to?(:has_provider?)).to eq true
52
+ expect(ProviderClass.has_provider?(:sum)).to eq true
53
+ expect(ProviderClass.has_provider?(:divid)).to eq false
54
+ end
55
+ end
56
+
57
+ describe "#has_providers_with_scope?" do
58
+ let(:klass){
59
+ Class.new Object do
60
+ include DataProvider::Base
61
+ provider [:a, :b ,:c]
62
+ provider :unscoped
63
+ end
64
+ }
65
+
66
+ it "return true if there are providers defined with an array identifier that start with the given prefix" do
67
+ expect(klass.new.has_providers_with_scope?(:unscoped)).to eq false
68
+ # byebug
69
+ expect(klass.has_providers_with_scope?(:a)).to eq true
70
+ expect(klass.new.has_providers_with_scope?([:a, :b])).to eq true
71
+ # scope means prefix, identfier may not be exactly the given array
72
+ expect(klass.new.has_providers_with_scope?([:a, :b, :c])).to eq false
73
+ end
74
+ end
75
+
76
+ describe "#take" do
77
+ it 'lets you take data from it' do
78
+ expect(provider.take(:sum)).to eq 7
79
+ expect(provider.take(:static)).to eq 'StaticValue'
80
+ end
81
+
82
+ it 'raise a ProviderMissingException when attempting to take from unknown provider' do
83
+ expect{provider.take(:unknown)}.to raise_error(DataProvider::ProviderMissingException)
84
+ end
85
+
86
+
87
+ it 'works from within a provider block' do
88
+ expect(provider.take(:billy)).to eq 'Billy Bragg'
89
+ end
90
+ end
91
+
92
+ describe "#try_take" do
93
+ it "acts like #take when the specified provider is present" do
94
+ expect(provider.try_take(:sum)).to eq 7
95
+ end
96
+
97
+ it "returns nil when the specified provider is not found" do
98
+ expect(provider.try_take(:square_root)).to eq nil
99
+ end
100
+ end
101
+
102
+ describe "#scoped_take" do
103
+ it 'lets a provider call providers within its own scope' do
104
+ expect(provider.take([:identification, :fullname])).to eq 'Billy Bragg'
105
+ end
106
+ end
107
+
108
+ describe "#give" do
109
+ it "lets you give data, creating a new data provider instance" do
110
+ updated_provider = provider.give :array => [1,80]
111
+ expect(provider.take(:sum)).to eq 7
112
+ expect(updated_provider.take(:sum)).to eq 81
113
+ end
114
+
115
+ it "allows for linked notation" do
116
+ expect(provider.give(:array => [7, -3]).take(:sum)).to eq 4
117
+ end
118
+
119
+ it "has an add_scope alias" do
120
+ expect(provider.add_scope(:array => [400, 20]).take(:sum)).to eq 420
121
+ end
122
+
123
+ it "has an add_data alias" do
124
+ expect(provider.add_data(:array => [400, 20]).take(:sum)).to eq 420
125
+ end
126
+ end
127
+
128
+ describe "#give!" do
129
+ it "lets you update the current provider with additional data" do
130
+ prov = ProviderClass.new(:data => {:array => [1,1,90]})
131
+ expect(prov.take(:sum)).to eq 92
132
+ prov.give!(:array => [3,90])
133
+ expect(prov.take(:sum)).to eq 93
134
+ end
135
+
136
+ it "allows for linked notation" do
137
+ expect(provider.give.give!(:array => [-1, -4]).take(:sum)).to eq -5
138
+ end
139
+
140
+ it "has an add_scope! alias" do
141
+ newprovider = provider.add_scope
142
+ newprovider.add_scope!(:array => [-1, -4])
143
+ expect(newprovider.given(:array)).to eq [-1,-4]
144
+ expect(newprovider.take(:sum)).to eq -5
145
+ end
146
+
147
+ it "has an add_data! alias" do
148
+ scoped_provider = provider.add_data(:array => []).add_data!(:array => [5, 5])
149
+ expect(scoped_provider.get_data(:array)).to eq [5,5]
150
+ expect(scoped_provider.take(:sum)).to eq 10
151
+ end
152
+ end
153
+
154
+ describe "#given" do
155
+ it "has a given method to get given data" do
156
+ expect(provider.given(:array)).to eq [1,2,4]
157
+ expect(provider.give(:array => 'array').given(:array)).to eq 'array'
158
+ end
159
+
160
+ it "has a get_data alias" do
161
+ expect(provider.get_data(:array)).to eq provider.given(:array)
162
+ end
163
+ end
164
+
165
+ describe "#provides" do
166
+ class SimpleProviders
167
+ include DataProvider::Base
168
+ provides({
169
+ :name => 'Paddy',
170
+ 'instrument' => :bass,
171
+ })
172
+ end
173
+
174
+ it "lets you request all currently available simple providers when called without a parameter" do
175
+ expect(SimpleProviders.provides).to eq({
176
+ :name => 'Paddy',
177
+ 'instrument' => :bass
178
+ })
179
+ end
180
+
181
+ it "lets you define simple providers" do
182
+ expect(SimpleProviders.new.take(:name)).to eq 'Paddy'
183
+ expect(SimpleProviders.new.take('instrument')).to eq :bass
184
+ end
185
+
186
+ it "works with has_provider?" do
187
+ expect(SimpleProviders.has_provider?(:name)).to eq true
188
+ expect(SimpleProviders.new.has_provider?('name')).to eq false
189
+ expect(SimpleProviders.has_provider?('instrument')).to eq true
190
+ expect(SimpleProviders.new.has_provider?(:instrument)).to eq false
191
+ end
192
+
193
+ it "lets you overwrite existing simple providers" do
194
+ SimpleProviders.provides({:name => 'Erik'})
195
+ expect(SimpleProviders.new.take(:name)).to eq 'Erik'
196
+ end
197
+
198
+ it "lets you write linked notation" do
199
+ expect(SimpleProviders.provides({:name => 'Lane'}).new.take(:name)).to eq 'Lane'
200
+ end
201
+
202
+ it "works with lambdas" do
203
+ expect(SimpleProviders.provides(:name => lambda{ 'Patrick' }).new.take(:name)).to eq 'Patrick'
204
+ end
205
+
206
+ it "works with Procs" do
207
+ expect(SimpleProviders.provides(:name => Proc.new{ 'St. Patrick' }).new.take(:name)).to eq 'St. Patrick'
208
+ end
209
+ end
210
+
211
+ describe "#add" do
212
+ module OddProviders
213
+ include DataProvider::Base
214
+ provides({1 => 'one'})
215
+ provider :three do 3 end
216
+ end
217
+
218
+ module OddOverwriteProviders
219
+ include DataProvider::Base
220
+ provides({1 => 'Uno', :five => 555})
221
+ provider :three do :tres end
222
+ end
223
+
224
+ class BasicProviders
225
+ include DataProvider::Base
226
+ provides({2 => '1'})
227
+ provider :four do '4' end
228
+ add OddProviders
229
+ end
230
+
231
+ it "lets you add providers from another module" do
232
+ expect(BasicProviders.has_provider?(1)).to eq true
233
+ expect(BasicProviders.has_provider?(2)).to eq true
234
+ expect(BasicProviders.has_provider?(:three)).to eq true
235
+ expect(BasicProviders.has_provider?(:four)).to eq true
236
+ # expect(BasicProviders.new.take(1)).to eq 'one'
237
+ expect(BasicProviders.new.take(:three)).to eq 3
238
+ end
239
+
240
+ it "lets you add providers from another module at runtime" do
241
+ expect(BasicProviders.has_provider?(:five)).to eq false
242
+ BasicProviders.add(OddOverwriteProviders)
243
+ expect(BasicProviders.has_provider?(:five)).to eq true
244
+ end
245
+
246
+ # for the following test the providers of OddOverwriteProviders
247
+ # have already been added (by the previous test)
248
+ it "lets overwrite providers" do
249
+ expect(BasicProviders.new.take(1)).to eq 'Uno'
250
+ expect(BasicProviders.new.take(:three)).to eq :tres
251
+ end
252
+ end
253
+
254
+ describe "#add_scoped" do
255
+ module ChildProviders
256
+ include DataProvider::Base
257
+ provider :name do "child" end
258
+ end
259
+
260
+ module GrandchildProviders
261
+ include DataProvider::Base
262
+ provider :name do "grandchild" end
263
+ provider [:age] do 1 end
264
+ provides({
265
+ :mommy => 'Wilma',
266
+ :daddy => 'Fret'
267
+ })
268
+ end
269
+
270
+ class ProviderKlass
271
+ include DataProvider::Base
272
+ provider :parent do 'parent' end
273
+ add_scoped ChildProviders, :scope => :child
274
+ add_scoped GrandchildProviders, :scope => [:child, :child]
275
+ end
276
+
277
+ it 'let you array-prefix the providers of an included module' do
278
+ expect(ProviderKlass.has_provider?(:parent)).to eq true
279
+ expect(ProviderKlass.has_provider?(:name)).to eq false
280
+ expect(ProviderKlass.has_provider?([:child, :name])).to eq true
281
+ expect(ProviderKlass.has_provider?([:child, :age])).to eq false
282
+ expect(ProviderKlass.has_provider?([:child, :child, :name])).to eq true
283
+ expect(ProviderKlass.has_provider?([:child, :child, :age])).to eq true
284
+ expect(ProviderKlass.has_provider?([:child, :child, :mommy])).to eq true
285
+ expect(ProviderKlass.has_provider?([:child, :child, :daddy])).to eq true
286
+ expect(ProviderKlass.new.take([:child, :name])).to eq 'child'
287
+ expect(ProviderKlass.new.take([:child, :child, :name])).to eq 'grandchild'
288
+ expect(ProviderKlass.new.take([:child, :child, :age])).to eq 1
289
+ expect(ProviderKlass.new.take([:child, :child, :mommy])).to eq 'Wilma'
290
+ expect(ProviderKlass.new.take([:child, :child, :daddy])).to eq 'Fret'
291
+ end
292
+ end
293
+
294
+ describe "provider_missing" do
295
+ it "lets you define a default fallback provider" do
296
+ klass = Class.new Object do
297
+ include DataProvider::Base
298
+ provider_missing do
299
+ "This provider don't exist!"
300
+ end
301
+ end
302
+
303
+ expect(klass.has_provider?(:message)).to eq false
304
+ expect(klass.new.take(:message)).to eq "This provider don't exist!"
305
+ end
306
+
307
+ it "provides the missing provider id through the private missing_provider method" do
308
+ klass = Class.new Object do
309
+ include DataProvider::Base
310
+ provider_missing do
311
+ "Missing #{missing_provider}"
312
+ end
313
+ end
314
+
315
+ expect(klass.new.take(:something)).to eq 'Missing something'
316
+ expect{klass.new.missing_provider}.to raise_error(NoMethodError)
317
+ end
318
+
319
+ it 'calls the fallback provider when using try_take with an unknown provider' do
320
+ klass = Class.new Object do
321
+ include DataProvider::Base
322
+ provider_missing do
323
+ "fallback_#{missing_provider}"
324
+ end
325
+ end
326
+
327
+ expect(klass.new.try_take(:cool)).to eq 'fallback_cool'
328
+ end
329
+ end
330
+
331
+ describe "fallback_provider?" do
332
+ it "lets you know if a fallback provider has been registered" do
333
+ klass = Class.new Object do
334
+ include DataProvider::Base
335
+ end
336
+
337
+ expect(klass.fallback_provider?).to eq false
338
+ expect(klass.new.fallback_provider?).to eq false
339
+
340
+ klass.provider_missing do
341
+ "New fallback!"
342
+ end
343
+
344
+ expect(klass.fallback_provider?).to eq true
345
+ expect(klass.new.fallback_provider?).to eq true
346
+ end
347
+ end
348
+ end
349
+
350
+ describe "Adding additional providers" do
351
+ module AdditionalProvider
352
+ include DataProvider::Base
353
+
354
+ provider 'provider2' do
355
+ '#2'
356
+ end
357
+ end
358
+
359
+ module OverwriteProvider
360
+ include DataProvider::Base
361
+
362
+ provider 'provider1' do
363
+ '#111'
364
+ end
365
+ end
366
+
367
+ class OriginalProvider
368
+ include DataProvider::Base
369
+
370
+ provider 'provider1' do
371
+ '#1'
372
+ end
373
+
374
+ add AdditionalProvider
375
+ add OverwriteProvider
376
+ end
377
+
378
+ it "lets you include modules with additional providers" do
379
+ expect(OriginalProvider.new.take('provider2')).to eq '#2'
380
+ end
381
+
382
+ it "lets you include modules with additional providers" do
383
+ expect(OriginalProvider.new.take('provider1')).to eq '#111'
384
+ end
385
+ end
386
+
387
+ describe "Array identifiers" do
388
+ module ArrayProviderModule
389
+ include DataProvider::Base
390
+
391
+ provider [:some, 'Stuff'] do
392
+ 'OtherStuff'
393
+ end
394
+ end
395
+
396
+ class ArrayProviderClass
397
+ include DataProvider::Base
398
+
399
+ provider [:some, 'Stuff'] do
400
+ 'SomeStuff'
401
+ end
402
+
403
+ # add ArrayProviderModule
404
+ end
405
+
406
+ let(:provider){
407
+ ArrayProviderClass.new
408
+ }
409
+
410
+ it "lets you use array as provider identifiers" do
411
+ expect(provider.take([:some, 'Stuff'])).to eq 'SomeStuff'
412
+ end
413
+
414
+ it "lets you overwrite existing providers with Array-based identifiers" do
415
+ expect(provider.take([:some, 'Stuff'])).to eq 'SomeStuff'
416
+
417
+ provider.class.add(ArrayProviderModule)
418
+ expect(provider.take([:some, 'Stuff'])).to eq 'OtherStuff'
419
+ end
420
+ end
@@ -0,0 +1,12 @@
1
+ # loads and runs all tests for the rxsd project
2
+ #
3
+ # Copyright (C) 2010 Mohammed Morsi <movitto@yahoo.com>
4
+ # Licensed under the AGPLv3+ http://www.gnu.org/licenses/agpl.txt
5
+
6
+ require 'rspec'
7
+
8
+ CURRENT_DIR=File.dirname(__FILE__)
9
+ $: << File.expand_path(CURRENT_DIR + "/../lib")
10
+
11
+ require 'data_provider'
12
+ require 'byebug'
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: data-provider
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Mark van de Korput
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-07-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: A library of Ruby classes to help create consistent data interfaces
28
+ email: dr.theman@gmail.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - ".gitignore"
34
+ - Gemfile
35
+ - Gemfile.lock
36
+ - LICENSE
37
+ - README.md
38
+ - Rakefile
39
+ - data-provider.gemspec
40
+ - lib/data_provider.rb
41
+ - lib/data_provider/base.rb
42
+ - lib/data_provider/provider.rb
43
+ - spec/data_provider_spec.rb
44
+ - spec/spec_helper.rb
45
+ homepage: https://github.com/markkorput/data-provider
46
+ licenses:
47
+ - MIT
48
+ metadata: {}
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '0'
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubyforge_project:
65
+ rubygems_version: 2.2.2
66
+ signing_key:
67
+ specification_version: 4
68
+ summary: A library of Ruby classes to help create consistent data interfaces
69
+ test_files: []