Successive form submission without losing data in Rails? - ruby-on-rails

I am confused between the controller and views interaction. I have this initial form which validates the csv file uploaded. (POST form).
After this form is validated successfully, I give the user the option to confirm the details which, and this confirm button acts as another form.
The thing is I want to keep the details from the previous form values saved in the params hash. So basically I want to perform a merge with the second form.
Is this possible? If so, can you help me with the code for the second form cause currently it overrides the previous form. Both forms point to the same function in the controller.
<% unless #contents.blank? || #errors.present? %>
<form name="confirm_bulk_order" method="post" enctype="multipart/form-data" class="search line" action="/orders/create_bulk_order" id="confirm_bulk_order">
<div class="search-btn-align" id="confirmButton">
<input type="submit" name="confirm_bulk_order" value="Confirm Order" class="lmargin10 uiButton">
</div>
</form>
<% else %>
<form name="upload_bulk_order_csv" method="post" enctype="multipart/form-data" class="search line" action="/orders/create_bulk_order" id="upload_bulk_order_csv">
<div class="fileformField">
<span class="formlabel"> Upload CSV File: </span>
<input class="required" required="true" type="file" name="datafile"/>
</div>
<div class="search-btn-align" id="uploadButton">
<%= submit_tag 'Validate Bulk Order', :class => 'lmargin10 uiButton' %>
</div>
</form>
<% end %>
In controller orders
def create_bulk_corder
if #errors.blank? and params[:confirm_bulk_order]=="Confirm Order"
#Send the final REST order call
else
#contents = read_csv_file(params[:datafile]) if params[:datafile].present?
validate_order(#contents)
#Populate #errors etc, etc
....
....
end
render
end
What all changes must I make for this to be possible?

You're losing your params when the confirm button is pressed because they're not part of the confirm form. You could avoid this by adding a hidden field:
<form name="confirm_bulk_order" method="post" enctype="multipart/form-data" class="search line" action="/orders/create_bulk_order" id="confirm_bulk_order">
<!-- This assumes that #contents is a simple value... it's probably not, so you might need several hidden_field_tags here, one for each part of #contents that you want in your params -->
<%= hidden_field_tag "contents", #contents %>
<!-- You probably also want to show the user some info about their submission here -->
<div class="search-btn-align" id="confirmButton">
<input type="submit" name="confirm_bulk_order" value="Confirm Order" class="lmargin10 uiButton">
</div>
</form>
If you go with this approach, be sure to re-validate params[:datafile] after submission, since a malicious user could change this param value to get around your validation logic.
Also, I suggest factoring your action into two separate actions, and likewise for the views. You've got if-else blocks where you really ought to have separate files.

I suggest maybe using a gem that deals with multi paged forms or wizards: https://www.ruby-toolbox.com/categories/rails_wizards

Related

Ruby on Rails: How to link two input fields and an object together when submitting form

Hi there. I was wondering how I could link 2 input fields together with an object when submitting a form.
At present I have a food menu that contains many food items. For each item in the menu, I wish to have two input fields linked to it. A check-box to select the item and a number field to enter the quantity of the item required.
When I click submit I would like to be able to access the selected items in the controller to which they were sent to and then be able to display each item in a designated view.
I was able to send the quantity of only a single item through. However, when I entered quantities for many food items, the resulting hash in the params was empty.
Is there any way I could send the item(s) selected + quantities entered as a key-value pair in the params when I click submit.
Edit(1):-
I am currently able to send the food items as a key-value pair but I would like to only send those where the checkbox is ticked.
Selecting food items and entering quantities
Resulting parameters:
{"1"=>{"quantity"=>"2"}, "2"=>{"quantity"=>""}, "3"=>{"quantity"=>"1"}, "4"=>{"quantity"=>""}, "5"=>{"quantity"=>""}, "6"=>{"quantity"=>""}, "7"=>{"quantity"=>""}, "8"=>{"quantity"=>""}, "9"=>{"quantity"=>""}, "10"=>{"quantity"=>""}, "11"=>{"quantity"=>""}, "12"=>{"quantity"=>""}}
Code:
<h2><u>Appetizers: -</u></h2>
<form action="/order/create" method="post">
<input type="hidden" value="<%= form_authenticity_token %>" name="authenticity_token">
<% #food.where(course: 'appetizer').each do |appetizer| %>
<ul>
<li>
<%= appetizer.name %> - <%= number_to_currency(appetizer.price, :unit => "£") %>
<input type="checkbox">
</li>
<label for="<%= appetizer.id %>_quantity">Qty:</label>
<input type="text"
name="<%= appetizer.id %>[quantity]"
size="2"
id="<%= appetizer.id %>_quantity">
</ul>
<% end %>
<input type="submit" value="Submit">
</form>
<br>
<%= link_to 'Back', menu_path %>
You can get quick answers, if you include a code snippet. Coming to your question -
Have you used the array notation for the input element names?
<input type="text" name="textbox[]" />
Using this you can get two arrays - one array for checkbooks and other for text boxes.. this should be equivalent of having a map.
See this
Post which talks about similar problem.

Rails Simple Form font awesome instead of radio buttons breaks form validation flow

I’m building a form now with Rails & Simple_form with validations on the model. In the form I have several collections of radio buttons.
For each of the radio buttons I’m hiding the actual button and adding a font awesome icon. I’ve tried this with f.collection_radio_buttons and by just replacing the simple_form f.input tag with the plain HTML it would otherwise generate. However, after form validation I can only get the values to return and the error messages to display when I stick to this format:
<%= f.input field_value, label: false, as: :radio_buttons, collection: [1,2,3,4,5] %>
It seems that almost any changes I make to the default radio button causes it to be excluded from the form validation flow. Values are being sent correctly though.
Basically, the form works, values are being retained even after validation failure. What’s going wrong is the error messages are not being displayed and the values aren’t placed back in their fields, so they’re not visible
Basically what I want is a fontawesome icon instead of a radio button, I get the feeling a lot of people have done this before but I can't seem to find many resources online regarding this.
Below is a rough example of the HTML/ERB I was experimenting with. With this the form works, icons are displayed and all seems pretty great until the form is re-rendered after validation failure. Then the values are loaded back into the field, but not displayed for these fields. Any validation errors are also not displayed.
<div class="form-group radio_buttons required rating_<%= field_value.to_s %>">
<input type="hidden" name="rating[<%= field_value.to_s %>]" value="">
<% (1..5).to_a.each do |number| %>
<span class="radio">
<label for="rating_<%= field_value.to_s %>_<%= number %>" id="<%= number %>" data-target=".rating_<%= field_value.to_s %>">
<input class="radio_buttons optional" type="radio" value=<%= number %> name="rating[<%= field_value.to_s %>]" id="rating_<%= field_value.to_s %>_<%= number %>">
<i class="fa fa-star fa-2x"></i>
</label>
</span>
<% end %>
</div>

Rails: How to link html multiple-choice questions to a database value

I'm trying to get a user's quiz answers saved to a database. This presumably should happen when they click the 'get my results' button, but prior to that - how do I 'link' a question to the appropriate value in the database?
Here is my example quiz form partial (which gets rendered in my page view):
<%= form_for([current_user]) do |f| %>
<h3>1. I have the final say in decisions made within the group I'm leading.</h3>
<div class="btn-group-vertical clearfix form-group" data-toggle="buttons">
<label class="btn btn-primary text-left">
<input name="options" id="option1" type="radio" onclick="multiChoiceClick(1, 1)">A. Always. I'm the leader and should have the final say
</label>
<label class="btn btn-primary text-left">
<input name="options" id="option2" type="radio">B. Sometimes, but I think the group should make decisions if possible
</label>
<label class="btn btn-primary text-left">
<input name="options" id="option3" type="radio">C. I generally don't get involved. The group can make their own decisions without my help
</label>
</div>
<p>
<%= f.submit("Get my results!") %>
</p>
<% end %>
Just as an example, how do I get this question linking to the database?
I'm using the Devise gem to get users logged in and out (that's all working fine). My User model has_many :quiz_answers and the QuizAnswer model belongs_to :user.
Can anyone tell me the immediate next step?
I think the next step is to use fields_for :quiz_answers in the form builder. In your User model you will have to add accepts_nested_attributes_for :quiz_answers. And in your controller you need to permit the relevant parameters. Also see the guide for Nested Forms.

Rails close without saving from edit page

I have a typical CRUD app, I would like to add a link next to the f.submit that allows you to go back to the index without saving changes. I thought it would be as simple as just making a link to the index, but it's saving changes anyway.
<%= button_to 'Close Without Saving', users_path %>
<%= f.submit %>
What's the rails way of handling this?
From the fine manual:
[button_to] Generates a form containing a single button that submits to the URL created by the set of options.
So using button_to inside a form will attempt to create a nested form but HTML forms don't nest. The result will be an HTML structure something like this:
<form>
<form><!-- from button_to -->
<input type="submit">
</form>
<input type="submit"><!-- from f.submit -->
</form>
But the browser will ignore the inner <form> and assume you meant this:
<form>
<input type="submit"><!-- from button_to -->
<input type="submit"><!-- from f.submit -->
</form>
Then pressing either <input type="submit"> will submit the outer form.
You can either create another submit button in the outer form and the controller can check which button was pressed or you can use link_to and style the link to match your submit button (or leave it styled like a link depending on your preference).
<button type="button" onClick="location.href='<%= users_path %>'">Close Without Saving</button>
<%= f.submit %>
This also worked... went back to basics and used good old fashioned HTML.

Why is simple_form not creating my fields and creating hidden fields instead?

This is my ruby code:
<%= simple_form_for([#video, #video.comments.new]) do |f| %>
<% f.association :comment_title %>
<% f.input :body %>
<% f.button :submit %>
<% end %>
This is the generated HTML markup:
<form accept-charset="UTF-8" action="/videos/485/comments" class="simple_form comment" id="new_comment" method="post">
<div style="margin:0;padding:0;display:inline">
<input name="utf8" type="hidden" value="✓">
<input name="authenticity_token" type="hidden" value="55xSU8JUe1SgipjAkAEvCvidFdJY3hv8Qz5VBqUSrdE=">
</div>
<input class="button" id="comment_submit" name="commit" type="submit" value="Create Comment">
</form>
Obviously it's not creating the :body input field and the association select list correctly. Why is this and how can I fix it?
Btw, a video has many comments, and a comment belongs to video. Also, a comment_title has many comments, and a comment belongs to a video. Comment_title is generated with virtual attributes.
Please let me know if there is any other code you would like to see.
Both of these are because of choices in your rails application. The first is that you have selected to configure the application to use utf8 for character encoding. The second is because by default the application is setup to protect against cross site request forgery attacks. The authenticity token ensures that the response coming back to the server when the user submits the form is actually from you and not some other source just watching your traffic and posting away to mess with your database.
Ok so the problem was that I needed to add the "=" to <%= in my form elements.

Resources