# Forms and post methods¶

In rare case will the user visiting a page hardcore input the url.There many ways to get inputs for user and one of them is form.Since it the common method will take look into it.

Let us assume when calculating sum of user input on url `/2/2`

your route was
`/sum/:first_number/:second`

with that assumption in mind(if you used another routes it ok just change content to fit your app).

**Change the content of route like**

Note the removable of variables of the route

*myapp.rb*

1 2 3 4 5 6 7 8 9 | #some code above this comment get '/sum' do @first_number =params[:first_number] @second_number =params[:second_number] erb:sum # use whatever template used for this end ## some routes below this comment |

Remove the content on the template you created to display sum result and replace with this form and other content.In my case I will use `sum.erb`

.

My assumption here is your created an erb file inside view directory
*sum.erb*

1 2 3 4 5 6 7 8 | <h3>Enter Your Values</h3> <form> <input name="first_number" type="text" placeholder="First Number" ><br> <input name="second_number" type="text" placeholder="Second Number"><br> <input type="submit" value="calculate"> </form> <p>The sum of <%[email protected]_number%> and <%[email protected]_number%> is <%= @first_number.to_f + @second_number.to_f%></p> |

This is template allow user to enter their data via form and see result after calculation

## Conditional Rendering¶

It is awkward that our form show us results even without entering.Let us deal with that.When you display only what you want be seen by user on browser when certain condition is met is known as conditional rendering.We can you control flow statement for this.

*sum.erb*

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <h3>Enter Your Values</h3> <form> <input name="first_number" type="text" placeholder="First Number" ><br> <input name="second_number" type="text" placeholder="Second Number"><br> <input type="submit" value="calculate"> </form> <% if @first_number != nil and @second_number != nil %> <%if @first_number.strip == "" or @second_number.strip==""%> <p> Kindly fill the form to calculate </p> <%else%> <p>The sum of <%[email protected]_number%> and <%[email protected]_number%> is <%= @first_number.to_f + @second_number.to_f%></p> <%end%> <%end%> |

When the form is first rendered first_name and second_name have values of `nil`

since we have not yet passed any data.Therefore result will not be render unless we hit calculate.But when we hit calculate with our form blank or if its content are spacebar or tab created param, we display `Kindly fill the form to calculate`

since `strip`

method remove all leading or trailing on a string the we compare value to empty string if true we request user to fill form.

If we enter value and click calculate we get the sum but there is catch when user enter no numeric value is give us result logically that's absurd but for now bare with me I wanna take deteour.We shall revisit soon.

## Rendering of different template¶

When we calculate the sum you realize that we the result on the same page/template.Well that's not the only way out and to be honest it was rather hectic
when render because we had to check whether our params were empty string. Form
are ussually give action which the routes the are to render at if not given like we did not give our on the previous example it renders on the same page.Let us add an action which will hit `/calculation_results`

in our application.Add it like so:

*sum.erb*

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <h3>Enter Your Values</h3> <form action="/calculation_result"> <input name="first_number" type="text" placeholder="First Number" ><br> <input name="second_number" type="text" placeholder="Second Number"><br> <input type="submit" value="calculate"> </form> <% if @first_number != nil and @second_number != nil %> <%if @first_number.strip == "" or @second_number.strip==""%> <p> Kindly fill the form to calculate </p> <%else%> <p>The sum of <%[email protected]_number%> and <%[email protected]_number%> is <%= @first_number.to_f + @second_number.to_f%></p> <%end%> <%end%> |

When we enter our values and try calculating error pops on our face.Route /`calculation_results`

is not there.Let us create in our application like so:

*myapp.rb*

1 2 3 4 5 6 | # other routes # /sum route get "/calculation_result" erb: results end #other routes |

This demands we create `results`

template kindly do so.

This new addition also demands refactor from in `/sum`

route block.We longer receive params there it's prime function is just now to render our form therefore:

Edit content of `/sum`

routes like so.

*myapp.rb*

1 2 3 4 5 | #other routes get '/sum' do erb:sum end # /calculate_results route |

We also have to factor `sum.erb`

file but remove all content outside the form tag.Cut them and copy them in `result.erb`

you created.One more refactor is required.We are not handling params coming to `calculate_results`

let us to that.

1 2 3 4 5 6 7 8 9 | # other routes # /sum route get "/calculation_result" do @first_number =params[:first_number] @second_number =params[:second_number] erb: results end # other routes |

This if `<% if @first_number != nil and @second_number != nil %>`

statement in `result.erb`

do serve us anymore There no way user will send nil value anymore, we have seperate the forms. Remove it

## Saving and accessing results in a file¶

### Saving¶

As you can see after calculation our result get lost and we can't get it back well http requests are stateless and our application just temporarily hold the information.What if we permanently want to store our information.File is one of storage we can use.Will go file class in our docs and see how it can help us.

*myapp.rb*

1 2 3 4 5 6 7 8 9 10 11 12 13 | # other routes # /sum route get "/calculation_result" do @first_number =params[:first_number].strip @second_number =params[:second_number].strip @sum = @first_number.to_f + @second_number.to_f File.open("results.txt", "a+") do |file| file.puts(@sum) end erb:results end # other routes |

Here we append results of our calculations into and a file `results.txt`

if it does not exist we create the file before appending.

### Reading from our store¶

It would be of no use to us if save our result and not be able to refer to them later.So let do just that, let first create a route `all_results`

.

*myapp.rb*

1 2 3 4 5 6 7 8 9 10 11 12 | # other routes #/calculation_result route get '/all_results' do def all_results return [] unless File.exist?("results.txt") File.read("results.txt").split("\n") end @all_results= all_results erb:all_results end # other routes |

*all_results.erb*

1 2 3 4 5 6 | <h1> All Results</h1> <ul> <%@all_results.each do |result| %> <li><%= result%></li> <% end %> <ul> |

Using conditional rendering ensure that user see `No results at given mome nt`

if there in no result in our file.

## post method¶

What if I told you we have been doing all wrong honestly.The `get`

method as http protocols dictates it should be used to **read** data but we just used it
to save our which very wrong.Let create a post method for `/sum`

url .Add this content *myapp.rb* file. **Tranfer content of /calculation_result** into our new route like so.Delete

`/calculation_result`

content.*myapp.rb*

1 2 3 4 5 6 7 8 9 10 11 12 13 | get '/sum' do erb:sum end post '/sum' do @first_number =params[:first_number].strip @second_number =params[:second_number].strip @sum = @first_number.to_f + @second_number.to_f File.open("results.txt", "a+") do |file| file.puts(@sum) erb:calculation_results end end |

`/sum`

route has both get and post methods.One is for read i.e getting the form other is for creating calcution results.It make sense now

## Validations¶

What if user enter wrong input for instance in sum route we expect only integer,the user enter non-numeric input for now application just to convert whatever the input to float and since non-numeric converted to interger or float returns 0.This should not be the case we shoud be case and I promised will visit well now this is the time.

*myapp.rb*

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | get "/calculation_results" do @first_number =params[:first_number].strip @second_number =params[:second_number].strip @empty_error = nil @invalid_values = nil unless @first_number.empty? or @second_number.empty? @empty_error = "Kindly enter value " end regular_expression = /^[+-]?((\d+(\.\d*)?)|(\.\d+))$/ if regular_expression.match?(@first_number) and regular_expression(@second_number) @invalid_values = "Kindly Enter Numeric Values Only" else @sum = @first_number + @second_number end erb: end |