# Best way to validate input values

**URL:** <https://www.ruby-forum.com/t/best-way-to-validate-input-values/151159>\
**Category:** Rails\
**Created:** [October 17, 2008, 1:40pm UTC](https://www.ruby-forum.com/t/best-way-to-validate-input-values/151159 "2008-10-17T13:40:58Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![jicksta](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/7ba0ec/32.png) [@jicksta](https://www.ruby-forum.com/u/jicksta)\
**Post date:** [October 17, 2008, 1:40pm UTC](https://www.ruby-forum.com/t/best-way-to-validate-input-values/151159/1 "2008-10-17T13:40:58Z")

</div>

Hi, I have a form that submits values from text fields and a check box.  
The values posted are: camp location name, number of nights, number of  
parents, number of children, value from the check box “family claim”.  
Where camp name can’t be nil, nights can’t be more than 2, parents and  
children together can’t be more than 8 and if there are no children  
specified check box can’t be checked. Here’s my unsuccessful  
implementation for this:

def add\_to\_cart  
begin  
cart=find\_cart  
camp\_loc = params[:camp][:id]  
nights=params[:nights]  
parents=params[:parents]  
children=params[:children]  
family\_rate\_claim=params[:family\_claim]  
rescue  
redirect\_to\_booking(“Invalid input.”)  
end  
if camp\_loc.blank? || nights.blank? || parents.blank?  
redirect\_to\_booking(“Fields with ‘\*’ are required fields.”)  
elsif (nights.to\_i \> 2) || ((parents.to\_i + children.to\_i) \> 8)  
redirect\_to\_booking(“Limitation: Maximum stay of 2 nights with group  
of maximum 8 people.”)  
elsif children.nil? and family\_rate\_claim == “1”  
redirect\_to\_booking(“You are not eligible for claiming family  
rate.”)  
else  
…add the stuff in the cart  
end  
end

def redirect\_to\_booking(msg)  
flash[:notice]=msg  
render :action =\> :online\_booking  
end

When I click the button without giving anything as the input I get this:

Render and/or redirect were called multiple times in this action. Please  
note that you may only call render OR redirect, and at most once per  
action. Also note that neither redirect nor render terminate execution  
of the action, so if you want to exit an action after redirecting, you  
need to do something like “redirect\_to(…) and return”.

but what I want is to to get redirected to the same page with error  
information.  
thanks…

---

<div class="post-metadata">

**Author:** ![jicksta](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/7ba0ec/32.png) [@jicksta](https://www.ruby-forum.com/u/jicksta)\
**Post date:** [October 17, 2008, 1:46pm UTC](https://www.ruby-forum.com/t/best-way-to-validate-input-values/151159/2 "2008-10-17T13:46:14Z")

</div>

the “render or redirect called multiple times” error is because you  
haven’t called ‘return’ after you called ‘render’ or indeed  
‘redirect\_to’. It doesn’t actually do the render or redirect  
immediately. It only occurs after the method has returned.

RobL

---

<div class="post-metadata">

**Author:** ![jicksta](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/7ba0ec/32.png) [@jicksta](https://www.ruby-forum.com/u/jicksta)\
**Post date:** [October 17, 2008, 1:50pm UTC](https://www.ruby-forum.com/t/best-way-to-validate-input-values/151159/3 "2008-10-17T13:50:23Z")

</div>

I wouldn’t do any vaildation in the controller, its messy and not ideal.

I’d have some kind of ‘Booking’ object which presumably is what you are  
adding to your cart and validate it inside that using the rails  
validation helpers.

RobL

---

<div class="post-metadata">

**Author:** ![jicksta](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/7ba0ec/32.png) [@jicksta](https://www.ruby-forum.com/u/jicksta)\
**Post date:** [October 17, 2008, 2:02pm UTC](https://www.ruby-forum.com/t/best-way-to-validate-input-values/151159/4 "2008-10-17T14:02:42Z")

</div>

Jay P. wrote:

you specific problem here is -

…

> rescue  
> redirect\_to\_booking(“Invalid input.”)  
> end

You render here

> if camp\_loc.blank? || nights.blank? || parents.blank?  
> redirect\_to\_booking(“Fields with ‘\*’ are required fields.”)  
> elsif (nights.to\_i \> 2) || ((parents.to\_i + children.to\_i) \> 8)  
> redirect\_to\_booking(“Limitation: Maximum stay of 2 nights with group  
> of maximum 8 people.”)  
> elsif children.nil? and family\_rate\_claim == “1”  
> redirect\_to\_booking("You are not eligible for claiming family

And also here

Do .

return( redirect\_to\_booking(“Invalid input.”) )

So your code doesn’t fall through.

---

<div class="post-metadata">

**Author:** ![jicksta](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/7ba0ec/32.png) [@jicksta](https://www.ruby-forum.com/u/jicksta)\
**Post date:** [October 17, 2008, 4:06pm UTC](https://www.ruby-forum.com/t/best-way-to-validate-input-values/151159/5 "2008-10-17T16:06:42Z")

</div>

On Oct 17, 4:55 am, Andrew P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> You render here
> 
> Do .
> 
> return( redirect\_to\_booking(“Invalid input.”) )
> 
> So your code doesn’t fall through.

I think there’s a relationship between the problem you are  
experiencing and the face that you are performing validations in your  
controller and not your model. As Rob said above, you should move the  
validations:

> if camp\_loc.blank? || nights.blank? || parents.blank?  
> elsif (nights.to\_i \> 2) || ((parents.to\_i + children.to\_i) \> 8)  
> elsif children.nil? and family\_rate\_claim == “1”

to your model and use ActiveRecord validations:

[http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html](http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html)

and

callbacks:

[http://api.rubyonrails.com/classes/ActiveRecord/Callbacks.html](http://api.rubyonrails.com/classes/ActiveRecord/Callbacks.html)

to implement the validations in your models

Then you could call save (or valid?) and use error\_messages\_for (vs.  
flash) to display your messages. This is all in addition to calling  
return with each render.

---

<div class="post-metadata">

**Author:** ![jicksta](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/7ba0ec/32.png) [@jicksta](https://www.ruby-forum.com/u/jicksta)\
**Post date:** [October 17, 2008, 4:06pm UTC](https://www.ruby-forum.com/t/best-way-to-validate-input-values/151159/6 "2008-10-17T16:06:41Z")

</div>

On Oct 17, 4:55 am, Andrew P. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> You render here
> 
> Do .
> 
> return( redirect\_to\_booking(“Invalid input.”) )
> 
> So your code doesn’t fall through.

I think there’s a relationship between the problem you are  
experiencing and the face that you are performing validations in your  
controller and not your model. As Rob said above, you should move the  
validations:

> if camp\_loc.blank? || nights.blank? || parents.blank?  
> elsif (nights.to\_i \> 2) || ((parents.to\_i + children.to\_i) \> 8)  
> elsif children.nil? and family\_rate\_claim == “1”

to your model and use ActiveRecord validations:

[http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html](http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html)

and

callbacks:

[http://api.rubyonrails.com/classes/ActiveRecord/Callbacks.html](http://api.rubyonrails.com/classes/ActiveRecord/Callbacks.html)

to implement the validations in your models

Then you could call save (or valid?) and use error\_messages\_for (vs.  
flash) to display your messages. This is all in addition to calling  
return with each render.

---

<div class="post-metadata">

**Author:** ![jicksta](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/7ba0ec/32.png) [@jicksta](https://www.ruby-forum.com/u/jicksta)\
**Post date:** [October 18, 2008, 2:32am UTC](https://www.ruby-forum.com/t/best-way-to-validate-input-values/151159/7 "2008-10-18T02:32:28Z")

</div>

Thanks guys for your suggestions. I have now moved all the validations  
to the model class and ended up with couple of question again. I’ve done  
like the following:

## MODEL CLASS:

class Cart \< ActiveRecord::Base  
validates\_presence\_of :campsite, :arrival\_date, :nights, :parents,  
:total

def validate  
errors.add(:nights, “should be equal to or less than 2”) if nights \>  
2  
errors.add(:total, “should be greater than 0”) if total \< 0.01  
end

## end

## CONTROLLER:

def add\_to\_cart  
cart=find\_cart  
if params[:family\_claim] != “1”  
total = (((params[:parents].to\_i + params[:children].to\_i) \* 4.85)

- params[:nights].to\_i)  
else  
total = (19.4 \* params[:nights].to\_i)  
end  
cart=Cart.create(:campsite =\> params[:camp][:id], :arrival\_date =\>  
params[:arrival\_date],  
:nights =\> params[:nights], :parents =\>  
params[:parents],  
:children =\> params[:children], :family\_claim =\>  
params[:family\_claim],  
:total =\> total)  
if cart.save  
@cart \<\< cart.id  
@cart\_details = find\_items\_in\_session  
else  
render :action =\> :online\_booking  
end  
end

* * *

## VIEW:

\<%=error\_messages\_for 'cart'%\> \<%form\_tag :action=\>:add\_to\_cart do%\> 

 ........... \<%end%\>
--------------------------------------------------------------------------------

1)Now, when I give 3 or more for the number of nights, online\_booking  
should be rendered again with the message “should be equal to or less  
than 2”, isn’t it? but I don’t get any message just the online\_booking  
page is redisplayed.

2)In the validation I have to validate that the number of parents and  
children together can’t be more than 8 (children can be null so it’s not  
checked). How do I do this?

## 3)One field gets replaced by partial before the form is submitted. So, if I submit the form before making that partial loaded, id for that field is passed as params[:campsite] and params[:camp][:id] if the partial is loaded. How can I check for this? In the controller I’m tried to do:

## if !params[:camp][:id].nil? camp\_loc = params[:camp][:id] else camp\_loc = params[:campsite] end

but failed and I think the reason is: params[:camp][:id] is no where to  
be found if the partial is not loaded and if I try with  
params[:campsite] its the same if the partial is loaded. So, how can I  
solve it as it gives me error in the same line where the if clause is?

thanks.
