lib/rom/http/dataset.rb in rom-http-0.4.0 vs lib/rom/http/dataset.rb in rom-http-0.5.0
- old
+ new
@@ -1,10 +1,15 @@
require 'rom/http/dataset/response_transformers/schemad'
require 'rom/http/dataset/response_transformers/schemaless'
module ROM
module HTTP
+ # HTTP Dataset
+ #
+ # Represents a specific HTTP collection resource
+ #
+ # @api public
class Dataset
include Enumerable
include Dry::Equalizer(:config, :options)
include ROM::Options
@@ -26,101 +31,291 @@
return @default_response_handler if Undefined === handler
@default_response_handler = handler
end
end
+
+ # HTTP Dataset interface
+ #
+ # @param [Hash] config the Gateway's HTTP server configuration
+ #
+ # @param [Hash] options dataset configuration options
+ # @option options [Symbol] :request_method (:get) The HTTP verb to use
+ # @option options [Array] :projections ([]) Keys to select from response tuple
+ # @option options [String] :path ('') URI request path
+ # @option options [Hash] :headers ({}) Additional request headers
+ # @option options [Hash] :params ({}) HTTP request parameters
+ #
+ # @api public
def initialize(config, options = {})
@config = config
@response_transformer = ResponseTransformers::Schemaless.new
super(options)
end
+ # @overload response_transformer
+ # Return the current response transformer
+ #
+ # @overload response_transformer(transformer)
+ # Set a new response transformer
+ #
+ # @param transformer [#call] The new response transformer
+ #
+ # @api private
def response_transformer(transformer = Undefined)
return @response_transformer if Undefined === transformer
@response_transformer = transformer
end
+ # Return the gateway's URI
+ #
+ # @return [String]
+ #
+ # @raise [Error] if the configuration does not contain a URI
+ #
+ # @api public
def uri
config.fetch(:uri) { fail Error, ':uri configuration missing' }
end
+ # Return request headers
+ #
+ # Merges default headers from the Gateway configuration and the
+ # current Dataset
+ #
+ # @example
+ # config = { Accepts: 'application/json' }
+ # users = Dataset.new(config, headers: { 'Cache-Control': 'no-cache' }
+ # users.headers
+ # # => {:Accepts => "application/json", :'Cache-Control' => 'no-cache'}
+ #
+ # @return [Hash]
+ #
+ # @api public
def headers
config.fetch(:headers, {}).merge(options.fetch(:headers, {}))
end
+ # Return the dataset name
+ #
+ # @return [String]
+ #
+ # @api public
def name
config[:name].to_s
end
+ # Return the dataset path
+ #
+ # @example
+ # Dataset.new(config, path: '/users').path
+ # # => 'users'
+ #
+ # @return [String] the dataset path, without a leading slash
+ #
+ # @api public
def path
options[:path].to_s.sub(%r{\A/}, '')
end
+ # Return the dataset path
+ #
+ # @example
+ # Dataset.new(config, path: '/users').path
+ # # => '/users'
+ #
+ # @return [string] the dataset path, with leading slash
+ #
+ # @api public
def absolute_path
'/' + path
end
+ # Return a new dataset with given headers
+ #
+ # @param headers [Hash] The new headers
+ #
+ # @note this _replaces_ the dataset's currently configured headers.
+ # To non-destructively add a new header, use `#add_header`
+ #
+ # @example
+ # users = Dataset.new(config, headers: { Accept: 'application/json' })
+ # users.with_headers(:'X-Api-Key' => '1234').headers
+ # # => { :'X-Api-Key' => '1234' }
+ #
+ # @return [Dataset]
+ #
+ # @api public
def with_headers(headers)
__new__(config, options.merge(headers: headers))
end
+ # Return a new dataset with additional header
+ #
+ # @param header [Symbol] the HTTP header to add
+ # @param value [String] the header value
+ #
+ # @example
+ # users = Dataset.new(config, headers: { Accept: 'application/json' })
+ # users.add_header(:'X-Api-Key', '1234').headers
+ # # => { :Accept => 'application/json', :'X-Api-Key' => '1234' }
+ #
+ # @return [Dataset]
+ #
+ # @api public
def add_header(header, value)
with_headers(headers.merge(header => value))
end
+ # Return a new dataset with additional options
+ #
+ # @param opts [Hash] the new options to add
+ #
+ # @return [Dataset]
+ #
+ # @api public
def with_options(opts)
__new__(config, options.merge(opts))
end
+ # Add a new set projection to the result set
+ #
+ # @param [Array, *args] projections the keys to add to the projections
+ #
+ # @example
+ # users = Dataset.new(config, projections: [:login])
+ # users.project(:email, :name).projections
+ # # => [:login, :email, :name]
+ #
+ # @return [Dataset]
+ #
+ # @api public
def project(*args)
projections = args.first.is_a?(::Array) ? args.first : args
with_options(
projections: (self.projections + projections)
)
end
+ # Return a new dataset with a different path
+ #
+ # @param path [String] the new request path
+ #
+ # @example
+ # users.with_path('/profiles').path
+ # # => 'profiles'
+ #
+ # @return [Dataset]
+ #
+ # @api public
def with_path(path)
with_options(path: path)
end
+ # Return a new dataset with a modified path
+ #
+ # @param path [String] new path fragment
+ #
+ # @example
+ # users.append_path('profiles').path
+ # # => users/profiles
+ #
+ # @return [Dataset]
+ #
+ # @api public
def append_path(path)
with_options(path: options[:path] + '/' + path)
end
+ # Return a new dataset with a different request method
+ #
+ # @param [Symbol] request_method the new HTTP verb
+ #
+ # @example
+ # users.request_method(:put)
+ #
+ # @return [Dataset]
+ #
+ # @api public
def with_request_method(request_method)
with_options(request_method: request_method)
end
+ # Return a new dataset with replaced request parameters
+ #
+ # @param [Hash] params the new request parameters
+ #
+ # @example
+ # users = Dataset.new(config, params: { uid: 33 })
+ # users.with_params(login: 'jdoe').params
+ # # => { :login => 'jdoe' }
+ #
+ # @return [Dataset]
+ #
+ # @api public
def with_params(params)
with_options(params: params)
end
+ # Iterate over each response value
+ #
+ # @yield [Hash] a dataset tuple
+ #
+ # @return [Enumerator] if no block is given
+ # @return [Array<Hash>]
+ #
+ # @api public
def each(&block)
return to_enum unless block_given?
response.each(&block)
end
+ # Perform an insert over HTTP Post
+ #
+ # @params [Hash] params The request parameters to send
+ #
+ # @return [Array<Hash>]
+ #
+ # @api public
def insert(params)
with_options(
request_method: :post,
params: params
).response
end
+ # Perform an update over HTTP Put
+ #
+ # @params [Hash] params The request parameters to send
+ #
+ # @return [Array<Hash>]
+ #
+ # @api public
def update(params)
with_options(
request_method: :put,
params: params
).response
end
+ # Perform an delete over HTTP Delete
+ #
+ #
+ # @return [Array<Hash>]
+ #
+ # @api public
def delete
with_options(
request_method: :delete
).response
end
+ # Execute the current dataset
+ #
+ # @return [Array<hash>]
+ #
+ # @api public
def response
response_transformer.call(
response_handler.call(request_handler.call(self), self),
self
)