module Shamu::Services::RequestSupport

Include into services that support mutating resources to add basic {#with_request} and {Request} conventions.

Public Instance Methods

request_class( method ) click to toggle source

Used to interrogate the service for the {Request} class to use for a given method.

Combine with {Request#init_from} to prepare a request for use in a rails form ready to modify an existing entity.

@param [Symbol] method on the service that will be called. @return [Class] a class that inherits from Request.

# File lib/shamu/services/request_support.rb, line 17
def request_class( method )
  self.class.request_class( method )
end
request_for( method, entity = nil ) click to toggle source

Build a {Request} object, prepopulated with the current state of the resource to submit changes to the given `method`.

@param [Symbol] method that will be called with the generated request. @param [Entities::Entity] entity optional entity that will modified. @return [Request]

# File lib/shamu/services/request_support.rb, line 27
def request_for( method, entity = nil )
  request    = request_class( method ).new( entity )
  request.id = entity.id if entity && request.attribute?( :id )

  request
end

Private Instance Methods

extract_params( id, params ) click to toggle source

Support convenient calling convention on update/delete style methods that might pass an id and params or a single params hash with associated id.

@example

users.update user, name: "Changed"  # Backend service
users.update id: 1, name: "Changed" # HTTP request params
# File lib/shamu/services/request_support.rb, line 108
def extract_params( id, params )
  if !params && !id.respond_to?( :to_model_id )
    params, id = id, id[ :id ] || id[ "id" ]
  end

  if params
    params = params.symbolize_keys if params.respond_to?( :symbolize_keys )
    params[ :id ] ||= id
  end

  [ id, params ]
end
request_class_by_alias( method ) click to toggle source
# File lib/shamu/services/request_support.rb, line 151
def request_class_by_alias( method )
  candidate =
    case method
    when :new  then "Create"
    when :edit then "Update"
    end

  if candidate && request_class_namespace.const_defined?( candidate )
    request_class_namespace.const_get( candidate )
  end
end
request_class_by_name( method ) click to toggle source
# File lib/shamu/services/request_support.rb, line 146
def request_class_by_name( method )
  camelized = method.to_s.camelize
  request_class_namespace.const_get( camelized ) if request_class_namespace.const_defined?( camelized )
end
request_class_default() click to toggle source
# File lib/shamu/services/request_support.rb, line 163
def request_class_default
  request_class_namespace.const_get( "Change" ) if request_class_namespace.const_defined?( "Change" )
end
request_class_namespace() click to toggle source
# File lib/shamu/services/request_support.rb, line 137
def request_class_namespace
  @request_class_namespace ||= ( name || "" ).sub( /(Service)?$/, "" )
                                             .singularize
                                             .concat( "Request" )
                                             .constantize
rescue NameError
  self
end
with_partial_request( params, request_class ) { |request| ... } click to toggle source

@!visibility public

Behaves the same as {#with_request} but always executes the block even if the params are not yet valid. Allows the block to populate the request with missing information before validating.

@param (see with_request) @return (see with_request) @see with_request

# File lib/shamu/services/request_support.rb, line 89
def with_partial_request( params, request_class, &block )
  request = request_class.coerce( params )
  sources = yield( request )

  result = Result.coerce( sources, request: request )
  request.complete( result.valid? )
  recache_entity( result.entity ) if result.valid? && result.entity

  result
end
with_request( params, request_class ) { |request, *args| ... } click to toggle source

@!visibility public

Respond to a {Request} returning a {Result} touple of the subject {Entities::Entity} and {Request}.

Before processing the `params` will be coerced and validated. If the request is invalid, the method will immediately return without yielding to the block.

If the block yields an {Entities::Entity} it will be assigned as the {Result#entity} in the returned {Result} object.

@param [Request,Hash] params of the request. @param [Class] request_class to coerce `params` to. @yield (request) @yieldparam [Request] request coerced and validated from `params`. @yieldreturn [Entities::Entity,#errors] the entity manipulated during

the request or an object that responds to #errors.

@return [Result] @example

def process_order( params )
  with_request params, ProcesOrderRequest do |request|
    order = Models::Order.find( request.id )

    # Custom validation
    next request.error( :base, "can't do that" ) if order.state == 'processed'

    request.apply_to( order )

    # If DB only validations fail, return errors
    next order unless order.save

    # All good, return an entity for the order
    scorpion.fetch OrderEntity, { order: order }
  end
end
# File lib/shamu/services/request_support.rb, line 72
def with_request( params, request_class, &block )
  with_partial_request params, request_class do |request, *args|
    next unless request.valid?

    yield request, *args
  end
end