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

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.

Related

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>

Adding a new Favorite: Creating a form with the current_user.id

I'm trying to create a form that will save the current_user.id. Something is funky in my controller. Any thoughts on obvious issues?
View (new.html.erb)
<!-- Label and input for user_id -->
<div class="form-group">
<label for="user_id" class="control-label">
User
</label>
<%= current_user.id %>
<input type="hidden" name="user_id" value="<%= current_user.id%>">
</div>
Controller (favorites_controller.rb)
def create
#favorite = Favorite.new
#favorite.dish_comment = params[:dish_comment]
#favorite.user_id = curent_user.id
d = params[:dish_id]
r = params[:restaurant_id]
problem code:
#favorite.user_id = curent_user.id
I thing you should put an # in front of your current_user to make it accessible in the ERB and in the controller.
Plus, once you save the current_user, you should user params[:user_id] to match the erb (input name is user_id).
Please look at the rails server output, it will tell you what parameters are submitted in the request.
Thanks #jackhaskeyboard. I spelled "current" wrong.
I'm now getting the following errors: Add Favorite Error Messages
1. "User has already been taken"
-A user should be able to post unlimited favorites, so I"m not sure why this is occurring.
"Dishing can't be blank"
-The purpose of this form is to select two variables (dish & restaurant), search the dishing join table to see if that combination exists. If not, create one, if so, grab the dishing_id, and use it to create a new favorite entry (user & dish/restaurant)
Here's my view code:
<div class="row">
<div class="col-md-12">
<form action="/create_favorite" method="post">
<!-- Hidden input for authenticity token to protect from forgery -->
<input name="authenticity_token" type="hidden" value="<%= form_authenticity_token %>">
<!-- Label and input for user_id -->
<div class="form-group">
<% current_user.id %>
<input type="hidden" name="user_id" value="<%= current_user.id%>">
</div>
<!-- Label and input for dishing_id -->
<div class="form-group">
<label for="dishing_id" class="control-label">
Dish
</label>
<%= select_tag(:dish_id, options_from_collection_for_select(Dish.all, 'id', 'dish_name')) %>
</div>
<!-- Label and input for restaurant_id -->
<div class="form-group">
<label for="restaurant_id" class="control-label">
Restaurant
</label>
<%= select_tag(:restaurant_id, options_from_collection_for_select(Restaurant.all, 'id', 'name') ) %>
</div>
<button class="btn btn-success">
Create Favorite
</button>
or
Cancel
</form>
</div>
</div>

Successive form submission without losing data in 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

Dynamic changes in rails form (simpleform)

I'm trying to make a simple form with this general structure:
o accept o decline
[submit]
when the radio button accept is checked and submit pressed, I want it to change the state of my model (called Offer here).
BUT when the button decline is checked, the form needs to change to something like this:
o accept x decline
Please enter reason here: [text box]
[submit]
Having entered a (mandatory) reason for declining and pressing submit, will change the state of the model Offer too, but differently.
I'm currently having problems getting the form to display the way I want. I'm using SimpleForm and tried something like this:
<%= simple_form_for #offer do |f| %>
<%= f.input accepts, as: :radio_buttons %>
<%= f.input :r_comment, as: :text, :label => 'Please enter reason here:' , :input_html => { :rows => 2, } %>
<%= f.button :submit %>
<% end %>
This of course doesn't work, because there is no "accepts" method or variable defined for offers (and it shouldn't be!). As for dynamically showing the input text box, I don't even have the slightest clue.
I'd be glad for any help you might offer,
Lordylike
UPDATE: HTML generated by simple_form
<div class="control-group radio_buttons optional">
<label class="radio_buttons optional control-label">Accept?</label>
<div class="controls">
<label class="radio">
<input class="radio_buttons optional" id="offer_accepts_decline" name="offer[accepts]" type="radio" value="Decline" />
Decline
</label>
<label class="radio">
<input class="radio_buttons optional" id="offer_accepts_accept" name="offer[accepts]" type="radio" value="Accept" />
Accept
</label>
</div>
UPDATE: HTML generated for comment box
<div class="control-group text optional">
<label class="text optional control-label" for="offer_r_comment">Reason for rejection:</label>
<div class="controls">
<textarea class="text optional" cols="40" id="offer_r_comment" name="offer[r_comment]" rows="2">
</textarea>
</div>
</div>
i'm not a fan of formtastic or simple_form but looking at the documentation, you should be able to do the following
# offer.rb
attr_accessor :accepts
# view
<%= f.input :accepts, as: :radio_buttons, collection: ['Decline', 'Accept'] %>
# js which can be placed inline or in the assets. let's use coffee
# you should also limit the selector below to include the class or the id of the
# radio buttons. I'm also not familiar with the html generated by simple form so
# the selectors to show and hide should also be changed.
$ ->
$(':radio').change ->
if $(this).prop('checked')
if $(this).val() == 'Accept'
$('#offer_r_comment').show()
else
$('#offer_r_comment').hide()
UPDATE: non coffee version. you can place this inside a script tag and just throw in the view.
$(document).ready(function() {
$(':radio').change(function() {
if ($(this).prop('checked'))
if ($(this).val() == 'Accept')
$('#offer_r_comment').show();
else
$('#offer_r_comment').hide();
});
});

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