Module: ApiHammer::Rails
- Includes:
- HaltMethods
- Defined in:
- lib/api_hammer/halt.rb,
lib/api_hammer/rails.rb,
lib/api_hammer/check_required_params.rb,
lib/api_hammer/unmunged_request_params.rb
Defined Under Namespace
Modules: HaltMethods
Class Method Summary collapse
Instance Method Summary collapse
-
#check_required_params(*checks) ⇒ Object
halts with a 422 Unprocessable Entity and an appropriate error body if required params are missing .
-
#find_or_halt(model, find_attrs, options = {}) ⇒ Object
attempts to find and return the given model (an ActiveRecord::Base subclass) with the given attributes.
-
#halt(status, body, render_options = {}) ⇒ Object
halt and render the given body.
-
#halt_error(status, errors, render_options = {}) ⇒ Object
halt and render the given errors in the body on the 'errors' key.
-
#handle_halt(halt) ⇒ Object
handle a raised ApiHammer::Halt or subclass and render it.
-
#unmunged_request_params ⇒ Object
request parameters (not query parameters) without the nil/empty array munging that rails does.
Methods included from HaltMethods
#halt_accepted, #halt_already_reported, #halt_authentication_timeout, #halt_bad_gateway, #halt_bad_request, #halt_bandwidth_limit_exceeded, #halt_conflict, #halt_created, #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
6 7 8 9 10 |
# File 'lib/api_hammer/rails.rb', line 6 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 presentparams[:name]must be present
less simple:
check_required_params(:id, :person => [:name, :height], :lucky_numbers => Array)
params[:id]must be presentparams[:person]must be present and be a hashparams[:person][:name]must be presentparams[:person][:height]must be presentparams[:lucky_numbers]must be present and be an array
20 21 22 23 24 |
# File 'lib/api_hammer/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 |
#find_or_halt(model, find_attrs, options = {}) ⇒ Object
attempts to find and return the given model (an ActiveRecord::Base subclass) with the given attributes. halts with 404 (does not return) if that fails. options may specify a different status if that is required.
e.g.:
find_or_halt(User, :email => '[email protected]')
69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/api_hammer/halt.rb', line 69 def find_or_halt(model, find_attrs, ={}) = {:status => 404}.merge() record = model.where(find_attrs).first unless record attributes = find_attrs.map{|attr, val| "#{attr}: #{val}" }.join(", ") model_name = model.table_name model_name = model_name.singularize if model_name.respond_to?(:singularize) halt_error([:status], {model_name => ["Unknown #{model_name}! #{attributes}"]}) end record end |
#halt(status, body, render_options = {}) ⇒ Object
halt and render the given body
42 43 44 |
# File 'lib/api_hammer/halt.rb', line 42 def halt(status, body, = {}) raise(ApiHammer::Halt.new(body.inspect, body, .merge(:status => status))) end |
#halt_error(status, errors, render_options = {}) ⇒ Object
halt and render the given errors in the body on the 'errors' key
47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/api_hammer/halt.rb', line 47 def halt_error(status, errors, = {}) errors_as_json = errors.respond_to?(:as_json) ? errors.as_json : errors unless errors_as_json.is_a?(Hash) raise ArgumentError, "errors be an object representable in JSON as a Hash; got errors = #{errors.inspect}" end unless errors_as_json.keys.all? { |k| k.is_a?(String) || k.is_a?(Symbol) } raise ArgumentError, "errors keys must all be string or symbol; got errors = #{errors.inspect}" end unless errors_as_json.values.all? { |v| v.is_a?(Array) && v.all? { |e| e.is_a?(String) } } raise ArgumentError, "errors values must all be arrays of strings; got errors = #{errors.inspect}" end halt(status, {'errors' => errors}, ) 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/halt.rb', line 30 def handle_halt(halt) = halt. ? halt..dup : {} # rocket pants does not have a render method, just render_json if respond_to?(:render_json, true) render_json(halt.body || {}, ) else [:json] = halt.body || {} render() end end |
#unmunged_request_params ⇒ Object
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 |
# File 'lib/api_hammer/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 unless ActionDispatch::Request.method_defined?(:real_deep_munge) ActionDispatch::Request.send(:alias_method, :real_deep_munge, :deep_munge) end ActionDispatch::Request.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 ActionDispatch::Request.send(:alias_method, :deep_munge, :real_deep_munge) end end end |