Module: ApiHammer::Rails

Includes:
HaltMethods
Defined in:
lib/api_hammer/rails/halt.rb,
lib/api_hammer/rails.rb,
lib/api_hammer/rails/check_required_params.rb,
lib/api_hammer/rails/unmunged_request_params.rb

Overview

the contents of this file are to let you halt a controller in its processing without having to have a return in the actual action. this lets helper methods which do things like parameter validation halt.

it is desgined to function similarly to Sinatra's handling of throw(:halt), but is based around exceptions because rails doesn't catch anything, just rescues.

Defined Under Namespace

Classes: Halt

Class Method Summary collapse

Instance Method Summary collapse

Methods included from HaltMethods

#find_or_halt, #halt_accepted, #halt_already_reported, #halt_authentication_timeout, #halt_bad_gateway, #halt_bad_request, #halt_bandwidth_limit_exceeded, #halt_conflict, #halt_created, #halt_error, #halt_expectation_failed, #halt_failed_dependency, #halt_forbidden, #halt_found, #halt_gateway_timeout, #halt_gone, #halt_http_version_not_supported, #halt_im_a_teapot, #halt_im_used, #halt_insufficient_storage, #halt_internal_server_error, #halt_length_required, #halt_locked, #halt_loop_detected, #halt_method_not_allowed, #halt_moved_permanently, #halt_multi_status, #halt_multiple_choices, #halt_network_authentication_required, #halt_no_content, #halt_no_response, #halt_non_authoritative_information, #halt_not_acceptable, #halt_not_extended, #halt_not_found, #halt_not_implemented, #halt_not_modified, #halt_ok, #halt_partial_content, #halt_payment_required, #halt_permanent_redirect, #halt_precondition_failed, #halt_precondition_required, #halt_proxy_authentication_required, #halt_redirect, #halt_request_entity_too_large, #halt_request_header_fields_too_large, #halt_request_timeout, #halt_request_uri_too_long, #halt_requested_range_not_satisfiable, #halt_reset_content, #halt_see_other, #halt_service_unavailable, #halt_temporary_redirect, #halt_too_many_requests, #halt_unauthorized, #halt_unavailable_for_legal_reasons, #halt_unordered_collection, #halt_unprocessable_entity, #halt_unsupported_media_type, #halt_upgrade_required, #halt_use_proxy, #halt_variant_also_negotiates

Class Method Details

.included(klass) ⇒ Object



7
8
9
10
11
# File 'lib/api_hammer/rails.rb', line 7

def self.included(klass)
  (@on_included || []).each do |included_proc|
    included_proc.call(klass)
  end
end

Instance Method Details

#check_required_params(*checks) ⇒ Object

halts with a 422 Unprocessable Entity and an appropriate error body if required params are missing

simple:

check_required_params(:id, :name)
  • params[:id] must be present
  • params[:name] must be present

less simple:

check_required_params(:id, :person => [:name, :height], :lucky_numbers => Array)
  • params[:id] must be present
  • params[:person] must be present and be a hash
  • params[:person][:name] must be present
  • params[:person][:height] must be present
  • params[:lucky_numbers] must be present and be an array


20
21
22
23
24
# File 'lib/api_hammer/rails/check_required_params.rb', line 20

def check_required_params(*checks)
  errors = Hash.new { |h,k| h[k] = [] }
  check_required_params_helper(checks, params, errors, [])
  halt_unprocessable_entity(errors) if errors.any?
end

#halt(status, body, render_options = {}) ⇒ Object

halt and render the given body



42
43
44
# File 'lib/api_hammer/rails/halt.rb', line 42

def halt(status, body, render_options = {})
  raise(ApiHammer::Rails::Halt.new(body.inspect, body, render_options.merge(:status => status)))
end

#handle_halt(halt) ⇒ Object

handle a raised ApiHammer::Halt or subclass and render it



30
31
32
33
34
35
36
37
38
39
# File 'lib/api_hammer/rails/halt.rb', line 30

def handle_halt(halt)
  render_options = halt.render_options ? halt.render_options.dup : {}
  # rocket pants does not have a render method, just render_json 
  if respond_to?(:render_json, true)
    render_json(halt.body || {}, render_options)
  else
    render_options[:json] = halt.body || {}
    render(render_options)
  end
end

#unmunged_request_paramsObject

request parameters (not query parameters) without the nil/empty array munging that rails does



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/api_hammer/rails/unmunged_request_params.rb', line 3

def unmunged_request_params
  # Thread.exclusive is not optimal but we need to ensure that any other params parsing occurring in other 
  # threads is not affected by disabling munging
  #
  # TODO when we are on a rails which has ActionDispatch::Request::Utils.perform_deep_munge, use that instead
  # of clobbering methods
  @unmunged_params ||= Thread.exclusive do
    if ActionDispatch::Request.const_defined?(:Utils) && ActionDispatch::Request::Utils.respond_to?(:deep_munge)
      # rails 4
      deep_munge_owner = (class << ActionDispatch::Request::Utils; self; end)
    else
      # rails 3
      deep_munge_owner = ActionDispatch::Request
    end

    unless deep_munge_owner.method_defined?(:real_deep_munge)
      deep_munge_owner.send(:alias_method, :real_deep_munge, :deep_munge)
    end
    deep_munge_owner.send(:define_method, :deep_munge) { |hash| hash }

    begin
      unmunged_params = nil
      newenv = request.env.merge('action_dispatch.request.request_parameters' => nil)
      ActionDispatch::ParamsParser.new(proc do |env|
        unmunged_params = env['action_dispatch.request.request_parameters']
      end).call(newenv)
      unmunged_params || ActionDispatch::Request.new(newenv).request_parameters
    ensure
      deep_munge_owner.send(:alias_method, :deep_munge, :real_deep_munge)
    end
  end
end