Commit 7b7c37bd by cole bradley

add recursion feature for validating nested attributes

add tests for nested attributes
parent 86c2ca0a
...@@ -7,6 +7,13 @@ module RailsParam ...@@ -7,6 +7,13 @@ module RailsParam
attr_accessor :param, :options attr_accessor :param, :options
end end
class MockController
include RailsParam::Param
attr_accessor :params
# def params
# end
end
def param!(name, type, options = {}) def param!(name, type, options = {})
name = name.to_s name = name.to_s
...@@ -17,8 +24,19 @@ module RailsParam ...@@ -17,8 +24,19 @@ module RailsParam
params[name] = (options[:default].call if options[:default].respond_to?(:call)) || options[:default] if params[name].nil? and options[:default] params[name] = (options[:default].call if options[:default].respond_to?(:call)) || options[:default] if params[name].nil? and options[:default]
params[name] = options[:transform].to_proc.call(params[name]) if params[name] and options[:transform] params[name] = options[:transform].to_proc.call(params[name]) if params[name] and options[:transform]
validate!(params[name], options) validate!(params[name], options)
if block_given?
controller = RailsParam::Param::MockController.new
controller.params = params[name]
# begin
yield(controller)
# exception.param, exception.options = name, options
# raise InvalidParameterError exception
# end
end
rescue InvalidParameterError => exception rescue InvalidParameterError => exception
exception.param, exception.options = name, options exception.param ||= name
exception.options ||= options
raise exception raise exception
end end
end end
...@@ -58,7 +76,7 @@ module RailsParam ...@@ -58,7 +76,7 @@ module RailsParam
return (/(false|f|no|n|0)$/i === param.to_s ? false : (/(true|t|yes|y|1)$/i === param.to_s ? true : nil)) if type == TrueClass || type == FalseClass || type == :boolean return (/(false|f|no|n|0)$/i === param.to_s ? false : (/(true|t|yes|y|1)$/i === param.to_s ? true : nil)) if type == TrueClass || type == FalseClass || type == :boolean
if type == BigDecimal if type == BigDecimal
param = param.delete('$,').strip.to_f if param.is_a?(String) param = param.delete('$,').strip.to_f if param.is_a?(String)
return BigDecimal.new(param, (options[:precision] || DEFAULT_PRECISION)) if type == BigDecimal return BigDecimal.new(param, (options[:precision] || DEFAULT_PRECISION))
end end
return nil return nil
rescue ArgumentError rescue ArgumentError
......
...@@ -17,4 +17,18 @@ class FakeController < ActionController::Base ...@@ -17,4 +17,18 @@ class FakeController < ActionController::Base
def new def new
render text: "new" render text: "new"
end end
def edit
param! :book, Hash, required: true do |b|
b.param! :title, String, required: true
b.param! :author, Hash do |a|
a.param! :first_name, String, required: true
a.param! :last_name, String, required: true
a.param! :age, Integer, required: true
end
b.param! :price, BigDecimal, required: true
end
render text: :book
end
end end
...@@ -15,6 +15,7 @@ module Rails ...@@ -15,6 +15,7 @@ module Rails
get '/fake/new' => "fake#new" get '/fake/new' => "fake#new"
get '/fakes' => "fake#index" get '/fakes' => "fake#index"
get '/fake/(:id)' => "fake#show" get '/fake/(:id)' => "fake#show"
get '/fake/edit' => "fake#edit"
end end
@routes @routes
end end
......
...@@ -10,6 +10,54 @@ describe FakeController, type: :controller do ...@@ -10,6 +10,54 @@ describe FakeController, type: :controller do
end end
end end
describe "nested_hash" do
it "validates nested properties" do
params = {
'book' => {
'title' => 'One Hundred Years of Solitude',
'author' => {
'first_name' => 'Garbriel Garcia',
'last_name' => 'Marquez',
'age' => '70'
},
'price' => '$1,000.00'
}}
get :edit, params
expect(controller.params[:book][:author][:age]).to eql 70
expect(controller.params[:book][:author][:age]).to be_kind_of Integer
expect(controller.params[:book][:price]).to eql 1000.0
expect(controller.params[:book][:price]).to be_instance_of BigDecimal
end
it "raises error when required nested attribute missing" do
params = {
'book' => {
'title' => 'One Hundred Years of Solitude',
'author' => {
'last_name' => 'Marquez',
'age' => '70'
},
'price' => '$1,000.00'
}}
expect { get :edit, params }.to raise_error { |error|
expect(error).to be_a(RailsParam::Param::InvalidParameterError)
expect(error.param).to eql("first_name")
expect(error.options).to eql({ :required => true })
}
end
it "passes when hash that's not required but has required attributes is missing" do
params = {
'book' => {
'title' => 'One Hundred Years of Solitude',
'price' => '$1,000.00'
}}
get :edit, params
expect(controller.params[:book][:price]).to eql 1000.0
expect(controller.params[:book][:price]).to be_instance_of BigDecimal
end
end
describe "InvalidParameterError" do describe "InvalidParameterError" do
it "raises an exception with params attributes" do it "raises an exception with params attributes" do
expect { get :index, sort: "foo" }.to raise_error { |error| expect { get :index, sort: "foo" }.to raise_error { |error|
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment