Skip to content

Commit

Permalink
Merge pull request #189 from ifeelgoods/nested_validator
Browse files Browse the repository at this point in the history
Add nested validator to validate nested children
  • Loading branch information
iNecas committed Jan 27, 2014
2 parents 9d12e39 + 2ced56e commit c202372
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 6 deletions.
14 changes: 14 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,20 @@ override parameters described on resource level.
#...
end
NestedValidator
-------------

You can describe nested parameters in depth if you provide a block with
description of nested values.

.. code:: ruby
param :comments, Array, :desc => "User comments" do
param :name, String, :desc => "Name of the comment", :required => true
param :comment, String, :desc => "Full comment", :required => true
end
Adding custom validator
-----------------------
Expand Down
45 changes: 40 additions & 5 deletions lib/apipie/validator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ def validate(value)
@array.include?(value.class)
end

def self.build(param_description, argument, options, proc)
if argument.is_a?(Array) && argument.first.class == Class
def self.build(param_description, argument, options, block)
if argument.is_a?(Array) && argument.first.class == Class && !block.is_a?(Proc)
self.new(param_description, argument)
end
end
Expand Down Expand Up @@ -273,7 +273,7 @@ def prepare_hash_params


# special type of validator: we say that it's not specified
class UndefValidator < Apipie::Validator::BaseValidator
class UndefValidator < BaseValidator

def validate(value)
true
Expand All @@ -290,7 +290,7 @@ def description
end
end

class NumberValidator < Apipie::Validator::BaseValidator
class NumberValidator < BaseValidator

def validate(value)
self.class.validate(value)
Expand All @@ -311,7 +311,7 @@ def self.validate(value)
end
end

class BooleanValidator < Apipie::Validator::BaseValidator
class BooleanValidator < BaseValidator

def validate(value)
%w[true false].include?(value.to_s)
Expand All @@ -328,6 +328,41 @@ def description
end
end

class NestedValidator < BaseValidator

def initialize(param_description, argument, param_group)
super(param_description)
@validator = Apipie::Validator:: HashValidator.new(param_description, argument, param_group)
@type = argument
end

def validate(value)
value ||= [] # Rails convert empty array to nil
return false if value.class != Array
value.each do |child|
return false unless @validator.validate(child)
end
true
end

def process_value(value)
value ||= [] # Rails convert empty array to nil
@values = []
value.each do |child|
@values << @validator.process_value(child)
end
@values
end

def self.build(param_description, argument, options, block)
self.new(param_description, block, options[:param_group]) if block.is_a?(Proc) && block.arity == 0 && argument == Array
end

def description
"Must be an Array of nested elements"
end
end

end
end

61 changes: 61 additions & 0 deletions spec/controllers/users_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,67 @@ def compare_hashes(h1, h2)
assert_response :success
end

describe "nested elements" do

context "with valid input" do
it "should succeed" do
put :update,
{
:id => 5,
:user => {
:name => "root",
:pass => "12345"
},
:comments => [
{
:comment => 'comment1'
},
{
:comment => 'comment2'
}
]
}

assert_response :success
end
end
context "with bad input" do
it "should raise an error" do
expect{ put :update,
{
:id => 5,
:user => {
:name => "root",
:pass => "12345"
},
:comments => [
{
:comment => 'comment1'
},
{
:comment => {bad_input: 5}
}
]
}
}.to raise_error(Apipie::ParamInvalid)
end
end
it "should work with empty array" do
put :update,
{
:id => 5,
:user => {
:name => "root",
:pass => "12345"
},
:comments => [
]
}

assert_response :success
end
end

end
end

Expand Down
5 changes: 4 additions & 1 deletion spec/dummy/app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,11 @@ def create
render :text => "OK #{params.inspect}"
end

api :PUT, "/users/:id", "Create user"
api :PUT, "/users/:id", "Update an user"
param_group :user
param :comments, Array do
param :comment, String
end
def update
render :text => "OK #{params.inspect}"
end
Expand Down

0 comments on commit c202372

Please sign in to comment.