Skip to content

Commit

Permalink
Merge pull request #188 from ifeelgoods/process_values
Browse files Browse the repository at this point in the history
Add optional functionality to pre process and extract parameters.
  • Loading branch information
iNecas committed Feb 21, 2014
2 parents 918018d + 169b17a commit c82bd58
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 5 deletions.
35 changes: 35 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,9 @@ required
allow_nil
Set true is ``nil`` can be passed for this param.

as
Use by the processing functionality to change the name of a key params.

meta
Hash or array with custom metadata.

Expand Down Expand Up @@ -503,6 +506,10 @@ validate_value
validate_presence
Check the params presence against the documentation.

process_params
Process and extract parameter defined from the params of the request
to the api_params variable

app_info
Application long description.

Expand Down Expand Up @@ -567,6 +574,34 @@ Example:
end
============
Processing
============

The goal is to extract and pre process parameters of the request.

For example Rails, by default, transforms empty array to nil value,
you want perhaps to transform it again to an empty array. Or you
want to support an enumeration type (comma separated values) and
you want automatically transform this string to an array.

To use it, set processing_value configuration variable to true.
In your action, use api_params variable instead of params.

Also by using `as` you can separate your API parameters
names from the names you are using inside your code.

To implement it, you just have to write a process_value
function in your validator:

For an enumeration type:

.. code:: ruby
def process_value(value)
value ? value.split(',') : []
end
============
Validators
============
Expand Down
7 changes: 5 additions & 2 deletions lib/apipie/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ class Configuration
:api_base_url, :doc_base_url, :required_by_default, :layout,
:default_version, :debug, :version_in_url, :namespaced_resources,
:validate, :validate_value, :validate_presence, :authenticate, :doc_path,
:show_all_examples

:show_all_examples, :process_params

alias_method :validate?, :validate
alias_method :required_by_default?, :required_by_default
Expand Down Expand Up @@ -37,6 +36,9 @@ def validate_presence
end
alias_method :validate_presence?, :validate_presence

def process_value?
@process_params
end
# set to true if you want to use pregenerated documentation cache and avoid
# generating the documentation on runtime (usefull for production
# environment).
Expand Down Expand Up @@ -125,6 +127,7 @@ def initialize
@version_in_url = true
@namespaced_resources = false
@doc_path = "doc"
@process_params = false
end
end
end
13 changes: 12 additions & 1 deletion lib/apipie/dsl_definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ module Apipie
module DSL

module Base
attr_reader :apipie_resource_descriptions
attr_reader :apipie_resource_descriptions, :api_params

private

Expand Down Expand Up @@ -194,6 +194,8 @@ def _apipie_define_validators(description)

old_method = instance_method(description.method)


# @todo we should use before_filter
define_method(description.method) do |*args|

if Apipie.configuration.validate_presence?
Expand All @@ -210,6 +212,15 @@ def _apipie_define_validators(description)
end
end

if Apipie.configuration.process_value?
@api_params = {}

description.params.each do |_, param|
# params processing
@api_params[param.as] = param.process_value(params[:"#{param.name}"]) if params.has_key?(param.name)
end
end

# run the original method code
old_method.bind(self).call(*args)
end
Expand Down
12 changes: 10 additions & 2 deletions lib/apipie/param_description.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ module Apipie
# validator - Validator::BaseValidator subclass
class ParamDescription

attr_reader :method_description, :name, :desc, :allow_nil, :validator, :options, :metadata, :show

attr_reader :method_description, :name, :desc, :allow_nil, :validator, :options, :metadata, :show, :as
attr_accessor :parent, :required

def self.from_dsl_data(method_description, args)
Expand Down Expand Up @@ -39,6 +38,7 @@ def initialize(method_description, name, validator, desc_or_options = nil, optio

@method_description = method_description
@name = concern_subst(name)
@as = options[:as] || @name
@desc = concern_subst(Apipie.markup_to_html(@options[:desc] || ''))
@parent = @options[:parent]
@metadata = @options[:meta]
Expand Down Expand Up @@ -74,6 +74,14 @@ def validate(value)
end
end

def process_value(value)
if @validator.respond_to?(:process_value)
@validator.process_value(value)
else
value
end
end

def full_name
name_parts = parents_and_self.map{|p| p.name if p.show}.compact
return name.to_s if name_parts.blank?
Expand Down
10 changes: 10 additions & 0 deletions lib/apipie/validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,16 @@ def validate(value)
return true
end

def process_value(value)
if @hash_params && value
return @hash_params.each_with_object({}) do |(key, param), api_params|
if value.has_key?(key)
api_params[param.as] = param.process_value(value[key])
end
end
end
end

def description
"Must be a Hash"
end
Expand Down
22 changes: 22 additions & 0 deletions spec/controllers/users_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -565,4 +565,26 @@ class IgnoredController < ApplicationController; end
end
end
end

describe "Parameter processing / extraction" do
before do
Apipie.configuration.process_params = true
end

it "process correctly the parameters" do
post :create, {:user => {:name => 'dummy', :pass => 'dummy', :membership => 'standard'}, :facts => nil}

expect(assigns(:api_params).with_indifferent_access).to eq({:user => {:name=>"dummy", :pass=>"dummy", :membership=>"standard"}, :facts => nil}.with_indifferent_access)
end

it "ignore not described parameters" do
post :create, {:user => {:name => 'dummy', :pass => 'dummy', :membership => 'standard', :id => 0}}

expect(assigns(:api_params).with_indifferent_access).to eq({:user => {:name=>"dummy", :pass=>"dummy", :membership=>"standard"}}.with_indifferent_access)
end

after do
Apipie.configuration.process_params = false
end
end
end

0 comments on commit c82bd58

Please sign in to comment.