data-provider
Ruby gem that provides a set of classes to build consistent data interfaces
Installation
Rubygems:
gem install data-provider
Bundler:
gem 'data-provider'
Examples
Define a provider class with some providers
require 'data_provider'
class BookProvider
include DataProvider::Base
# quick syntax for 'simple' providers
provides({
title: 'The Monkey Wrench Gang',
author: 'Edward Abbey'
})
# longer syntax for more complicated providers
provider :display_title do
"#{take(:author)} - #{take(:title)}"
end
provider :price do
9.99
end
end
Using a provider class
book_provider = BookProvider.new()
book_provider.take(:title) # => 'The Monkey Wrench Gang'
book_provider.take(:author) # => 'Edward Abbey'
book_provider.take(:display_title) # => 'Edward Abbey - The Monkey Wrench Gang'
book_provider.take(:price) # => 9.99
Data providers can be given data to customize their output
require 'data_provider'
class ProductProvider
include DataProvider::Base
provider :normal_price do
17.99
end
provider :discount_price do
take(:normal_price) - get_data(:discount)
end
end
product_provider = ProductProvider.new
product_provider.take(:normal_price) # => 17.99
product_provider.take(:discount_price) # => TypeError (discount data not given,): nil can't be coerced into Float
discounted_provider = product_provider.add_data(discount: 3.0) # returns a new instance of the same provider class
discounted_provider.take(:discount_price) # => 14.99
product_provider.take(:discount_price) # => TypeError (this instance didn't get the new data)
product_provider.add_data!(discount: 2) # => Updates this instance instead of creating a new one
product_provider.take(:discount_price) # => 15.99
product_provider.add_data!(discount: 4).take(:discount_price) #=> 13.99
Providers can be defined in a module and added to a provider class using the add class-method (not using include!)
require 'data-provider'
module BandInfo
include DataProvider::Base
provider :band do
'D4'
end
provider :bassPlayer do
'Paddy'
end
end
class Band
include DataProvider::Base
provider :band do
'Dillinger Four'
end
provider :drummer do
'Lane Pederson'
end
add BandInfo # note: add, not include!
end
band = Band.new
band.take(:band) # => 'D4', class provider was overwritten when the module got added
band.take(:bassPlayer) # => 'Paddy'
band.take(:drummer) #=> 'Lane Pederson'
Provider identifiers don't have to be symbols, they can be anything. Specifically array identifiers are suitable for creating data providers for hierarchical systems
require 'data_provider'
module AlbumProvider
include DataProvider::Base
provides({
title: 'Reinventing Axle Rose',
band: 'Against Me!'
[:band, :hometown] => 'Gainesville, FL'
})
end
class Catalog
include DataProvider::Base
provider [:music, :album, :bandname] do
# scoped_take is a method only available inside provider blocks,
# it lets a provider access other providers in the same 'scope',
# which means provider whose array-identifiers start with the same values,
# in this case the scope is [:music, :album]
scoped_take(:band).upcase
end
# by using `add_scoped` all providers of the added module, will be
# turned into array and prefixed with the given scope
add_scoped AlbumProvider, :scope => [:music, :album]
end
catalog = Catalog.new
catalog.take(:title) # => DataProvider::ProviderMissingException
catalog.take([:music, :album, :title]) # => 'Reinventing Axle Rose'
catalog.take([:music, :album, :band, :hometown]) # => 'Gainesville, FL'
catalog.take([:music, :album, :bandname]) # => 'AGAINST ME!"