Nested form with radio buttons
Hi there,
I am a Rails newbie .
I've been trying to build a nested form with radio buttons.
Let me explain it.
The form for choosing a staff from a list using a radio button
Let's say
O John
O Jake
O Blake
O All
and then choosing another a radio button option for multiple amount choices such as
O 2$
O 4$
O 8$
O 10$
Then finally a submit button to post the values to the paymentgate Api.
For example, John, 8$
<% #staffs.each do |staff| %>
<tr>
<td><%= staff.first_name %></td>
<td><%= staff.last_name %></td>
<td><input id="favorite_color_maroon" name="favorite_color" type="radio" value="maroon" /></td>
<input type="radio" name="picker" value="whatever_who_cares"> Whatever, who cares? </form>
<td><%= link_to 'Show', staff %></td>
<td><%= link_to 'Edit', edit_staff_path(staff) %></td>
<td><%= link_to 'Destroy', staff, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
<form action="/action_page.php">
<p>Please select your age:</p>
<input type="radio" id="age1" name="age" value="2">
<label for="staff_value">2</label><br>
<input type="radio" id="age2" name="age" value="4">
<label for="age2">4</label><br>
<input type="radio" id="age3" name="age" value="8">
<label for="age3">8</label><br><br>
<input type="radio" id="age4" name="age" value="10">
<label for="age4">10</label><br><br>
<input type="submit" value="Submit">
</form>
so how can I associate those radio buttons along with submit button to the external api?
Related
I am trying to use the same form to create a new database entry, display current DB information, and now update the DB information, but am stuck trying to patch in the create method within the controller. I have tried using first_or_initialize and find_or_initialize_by_name, but cant seem to get them to work for this situation. I was thinking of trying a if something.nil? / else type of design. I am new at this and any help is appreciated!
This is my controller (working currently to create new DB):
def create
params[:student].each do |student_id, attendance_type|
attendance = Attendance.new
attendance.attendance_type = attendance_type.to_i
attendance.student_id = student_id
attendance.event_id = params[:event_id]
attendance.save
end
redirect_to :back
end
HTML:
<tbody>
<% #students.each do |student| %>
<form class="form-group" action="/events/<%= #event.id %>/attendances" method="post">
<tr>
<div class="checkbox">
<td style="white-space:normal;"><%= link_to student.name, student_path(student.id) %></td>
<% attendance = student.attendances.find_by_event_id(#event.id) %>
<% if attendance.blank? || attendance.attendance_type == 1 %>
<td style="white-space:normal;"><label class="radio-inline"><input type="radio" name="student[<%= student.id %>]" checked="checked" id="inlineRadio1" value="1"></label></td>
<td style="white-space:normal;"><label class="radio-inline"><input type="radio" name="student[<%= student.id %>]" id="inlineRadio2" value="2"></label></td>
<td style="white-space:normal;"><label class="radio-inline"><input type="radio" name="student[<%= student.id %>]" id="inlineRadio3" value="3"></label></td>
<% elsif attendance.attendance_type == 2 %>
<td style="white-space:normal;"><label class="radio-inline"><input type="radio" name="student[<%= student.id %>]" id="inlineRadio1" value="1"></label></td>
<td style="white-space:normal;"><label class="radio-inline"><input type="radio" name="student[<%= student.id %>]" checked="checked" id="inlineRadio2" value="2"></label></td>
<td style="white-space:normal;"><label class="radio-inline"><input type="radio" name="student[<%= student.id %>]" id="inlineRadio3" value="3"></label></td>
<% else attendance.attendance_type == 3 %>
<td style="white-space:normal;"><label class="radio-inline"><input type="radio" name="student[<%= student.id %>]" id="inlineRadio1" value="1"></label></td>
<td style="white-space:normal;"><label class="radio-inline"><input type="radio" name="student[<%= student.id %>]" id="inlineRadio2" value="2"></label></td>
<td style="white-space:normal;"><label class="radio-inline"><input type="radio" name="student[<%= student.id %>]" checked="checked" id="inlineRadio3" value="3"></label></td>
<% end %>
</div>
<% end %>
</tr>
<tr><%= button_to 'Submit', :class => 'btn btn-primary' %></tr>
</form>
</tbody>
Thank you in advance!
Hopefully this is your missing piece. I do not believe it will help with efficiency. I will explain after.
Using an attribute already existing for your model I would do the following to either find or create an attendance object for student with the id 10.
Attendance.where(:student_id => 10).first_or_create do |attendance|
attendance.event_id = 3 #arbitrary
attendance.attendance_type = 2 #arbitrary
end
OR
attendance = Attendance.where(:student_id => 10).first_or_initialize
# a bunch of ways to set attributes
# ... and then
attendance.save
Now, why this may be inefficient. If you are going through each student parameter and looping through some attribute you will incur multiple calls. For example, for 100 students you will end up doing 100 separate queries if you loop for a first_or_initialize on every student attribute set. What I suggest is mapping all of the parameters that you require together into one array, doing a where query and then looping through the array. Put them all into one create call as an array, and BAM you cut yourself some serious ActiveRecord overhead.
#Just giving some context to the student param keys
student_ids = params[:student].keys
#Query for all student ids
attendances = Attendance.where(student_id: student_ids)
#Get a list of ids by filtering out all of the existing ids
new_student_ids = student_ids - attendances.map{|a| a.student_id}
#Create an array to carry your hashes
attendances = Array.new
#Cycle through all of your non-created ids and build you create list
new_student_ids.each do |id|
attendances << {#assign all values as a hash by grabbing them from params[:student] using the iterating id}
end
#Create a bunch at once
Attendance.create attendances
I'm having this issue where I want to display the correct answer in a check box in Rails, to no avail.
The structure is further complicated by the fact that my models are nested into one another so that Survey not only has_many, but also accepts_nested_attributes_for Questions and Questions has_many Choices similarly. The problem is that I'm simply not able to get the box checked for the correct answer.
The data are saved to the database as a boolean in a column called correct_choice and this code for the show action shows the check boxes, but the correct choice is not checked:
<table class="col-md-10">
<thead>
<tr>
<% for question in #survey.questions do %>
<li><%= h question.content %></li>
<% for choice in question.choices do %>
<li><%= h choice.content %>
<%= h check_box(:choice, :correct_choice ) %>
<% end %>
</li>
</li>
<% end %>
</tr>
</thead>
</table>
I've read the documentation, but I cannot figure out how to apply it to my case. Can anybody point me in the right direction?
EDIT
This is the HTML that I get out:
<table class="col-md-10">
<thead>
<tr>
<li>Is this a question?</li>
<li>I'm not big. I'm having a breakdown.
<input name="correct_choice[content]" type="hidden" value="0" /><input type="checkbox" value="1" name="correct_choice[content]" id="correct_answer_content" />
<li>Come on, I'm not big.
<input name="correct_choice[content]" type="hidden" value="0" /><input type="checkbox" value="1" name="correct_choice[content]" id="correct_choice_content" />
<li>Who is hungry?
<input name="correct_choice[content]" type="hidden" value="0" /><input type="checkbox" value="1" name="correct_choice[content]" id="correct_choice_content" />
<li>Pass the cheese, please.
<input name="correct_choice[content]" type="hidden" value="0" /><input type="checkbox" value="1" name="correct_choice[content]" id="correct_choice_content" />
</li>
</li>
</tr>
</thead>
</table>
I figured it out thanks to advice from #davidwessman. What he told me was to display the html and inspect. I did and compared to the html from the edit action (the one that works).
It then became clear that I needed to use the check_box_tag command instead of check_box. This is the code that I now use:
<thead>
<tr>
<% for question in #survey.questions do %>
<li><%= h question.content %></li>
<% for choice in question.choices do %>
<li><%= h choice.content %>
<%= check_box_tag "correct_choice", "yes", answer.correct_choice %>
<% end %>
</li>
</li>
<% end %>
</tr>
</thead>
Normally, in order to get a date select in rails, I write this:
<%= form_for(:buddy, :url => {:action => :create}) do |f| %>
<%= f.date_select(:dob) %>
<%= f.submit("HI") %>
<% end %>
and get this html as a result:
<form action="/buddy/create" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓" /><input type="hidden" name="authenticity_token" value="Qs8RK+6gEt9ZoycMbMHwX4xMyoFpRvjA/El3cLnO30RXddr864WmEXzyAgYtXBe5Y9l0zC3UDw4ggRw1xYW1sg==" />
<select id="buddy_dob_1i" name="buddy[dob(1i)]">
<option value="2010">2010</option>
<!-- ETC -->
<select id="buddy_dob_2i" name="buddy[dob(2i)]">
<option value="1" selected="selected">January</option>
<!-- ETC -->
<select id="buddy_dob_3i" name="buddy[dob(3i)]">
<option value="1">1</option>
<!-- ETC -->
<input type="submit" name="commit" value="HI" />
But now I'm using bootstrap. If I use the bootstrap_form_for gem, I run into the problem that on small screens, the three selects get placed on top of each other, which is unacceptable. So I came up with what I thought was a good solution: to place each of the selects in a different field of a table, which prevents the behaviour. So I have written this code:
<%= form_for(:buddy, {:action => :create, :role => 'form'}) do |f| %>
<div class="form-group">
<label for="buddy_dob">Date of Birth</label>
<table class="table functional-table">
<tr>
<td>
<%= select_year(Date.today, {:start_year => DateTime.now.year, :end_year => DateTime.now.year - 117}, {:name => 'buddy[dob(1i)]', :id => 'buddy_dob_1i', :class => 'form-control'}) %>
</td>
<td>
<%= select_month(Date.today, {}, {:name => 'buddy[dob(2i)]', :id => 'buddy_dob_2i', :class => 'form-control'}) %>
</td>
<td>
<%= select_day(1, {}, {:name => 'buddy[dob(3i)]', :id => 'buddy_dob_3i', :class => 'form-control'}) %>
</td>
</tr>
</table>
</div>
<div class="form-group">
<%= f.submit("HI") %>
</div>
<% end %>
which produces this result:
<form role="form" action="/buddy/new" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓" /><input type="hidden" name="authenticity_token" value="6Ek01J6PIgzHl/NLpjI6V+kolUVCpw7jrQTF8eYT3ef98/8Dm6qWwuLG1kHnr92xBr0rCAY1+S1xzK60mli3EQ==" />
<div class="form-group">
<label for="buddy_dob">Date of Birth</label>
<table class="table functional-table">
<tr>
<td>
<select id="buddy_dob_1i" name="buddy[dob(1i)]" class="form-control">
<option value="2015" selected="selected">2015</option>
<!-- ETC -->
</td>
</tr>
</table>
<table class="table functional-table">
<tr>
<td>
<select id="buddy_dob_2i" name="buddy[dob(2i)]" class="form-control">
<option value="1" selected="selected">January</option>
<!-- ETC -->
</td>
</tr>
</table>
<table class="table functional-table">
<tr>
<td>
<select id="buddy_dob_3i" name="buddy[dob(3i)]" class="form-control">
<option value="1" selected="selected">1</option>
<!-- ETC -->
</td>
</tr>
</table>
<div class="form-group">
<input type="submit" name="commit" value="HI" />
</div>
</form>
The display for this works exactly as I want, however when I try to submit the form I am redirected to the action :new with no errors registered by rails and no entry created. I never reach :create. I suspect this might be because I've manually separated the date fields which date_select separates and then pieces back together and rails cannot handle this, but I am not sure. How can I fix this and get the form working?
You have nested forms - this is illegal! Most of the browsers will simply ignore the inner form tag, so you'll end up with a DOM structure as presented. The outer form does not specify the action attribute, so browsers will append the current path as an action, in this case - /buddy/new. I'm a little bit surprised you're not getting routing error here - did you by any chance use match /buddy/new without specifying the verb?
Anyway - the solution is to get rid of surrounding form (the one with the role) and instead attach this role to your form_for call:
<%= form_for(:buddy, url: {action: :create}, html: {role: :form) do |f| %>
SOLVED! I just changed form_for to form_tag and it now works as expected. Thanks to BroiSatse for the information about ActionDispatch knowing how to convert the params; it encouraged me to look elsewhere for problems.
Your select names are not "standard". buddy[dob(3i)] is not a valid name.
When the query is sent to Rails, a first module changes all the received names into params. Here, it can't, and fail.
You should set somethink like this : buddy[dob_month].
I actually want to my database entries to be empty each time the app is accessed. But i am not getting any idea regarding this. Below is my code which takes 3 inputs from user and displays them in tabular form but each time I display the table old entries are also getting displayed. I want that once all the entries are displayed the database should get cleared.
<p>enter the name with registration number of students</p>
<form accept-charset="UTF-8" action="/pages/add" method="post">
<input id="nam" name="nam" type="text">
<input id="reg" name="reg" type="text">
<input id="cls" name="cls" type="text">
<input name="commit" type="submit" class="btn" value="Add todo">
</form>
<table width="100%">
<tr>
<th>NAME</th>
<th>REGISTRATION NUMBER</th>
<th>CLASSES ATTENDED</th>
</tr>
<tr>
<% #pages.each do |t| %>
<td><%= t.name_student %></td>
<td><%= t.reg_no %></td>
<td><%= t.classes_at %></td>
</tr>
<% end %>
</table>
I have a form that is non-responsive for some reason and I'm stuck!
I have followed the RailsCast here but it's based on an older version of rails.
Here's my view code, pretty sure that's where my trouble is:
<%= form_tag publish_selected_posts_path do %>
<% #posts_inactive.each do |post| %>
<tr>
<td><%= check_box_tag "post_ids[]", post.id %></td>
<td><%= link_to post.title, post_path(post) %></td>
<td><%= post.created_at.to_s(:short) %></td>
<td><%= post.user.email %></td>
<td><%= post.user.email %></td>
<td><%= post.state.name %></td>
<td><%= post.city.name %></td>
<td><%= post.expire_date.to_s(:short) %></td>
<td>
<div>
<div class="dark" style="float:left;">
<%= link_to 'Edit', edit_post_path(post), :class => 'btn btn-mini dark' %>
</div>
<div style="float:left;">
<%= button_to 'Delete', post_path(post), :method => :delete, :confirm => 'Are you sure?', :class => 'btn btn-mini btn-danger' %>
</div>
<div class="dark" style="float:left;">
<%= link_to publish_link_text(post),
toggle_publish_post_path(post),
:class => 'btn btn-mini dark' %>
</div>
<div style="clear:both;">
</div>
</div>
</td>
</tr>
<% end %>
</tbody>
</table>
<%= submit_tag "Publish Selected", :class => 'btn btn-mini dark' %>
<% end %>
When I press the submit button, nothing is happening... As best I can tell, everything is as it should be based on the rails cast, but it's just not working.
Here's the HTML this form outputs:
<form accept-charset="UTF-8" action="/dashboard/posts" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="pwTuSXar01OT26FHf1bMyxKsSQ7MHWn/u3BQ9PmffS4=" /></div>
<tr>
<td><input id="post_ids_" name="post_ids[]" type="checkbox" value="29" /></td>
<td>Another Post</td>
<td>30 Nov 05:03</td>
<td>guitarjoe02#email.com</td>
<td>guitarjoe02#email.com</td>
<td>Alaska</td>
<td>Anchorage</td>
<td>28 Jan</td>
<td>
<div>
<div class="dark" style="float:left;">
Edit
</div>
<div style="float:left;">
<form action="/posts/29" class="button_to" method="post"><div><input name="_method" type="hidden" value="delete" /><input class="btn btn-mini btn-danger" data-confirm="Are you sure?" type="submit" value="Delete" /><input name="authenticity_token" type="hidden" value="pwTuSXar01OT26FHf1bMyxKsSQ7MHWn/u3BQ9PmffS4=" /></div></form>
</div>
<div class="dark" style="float:left;">
Publish
</div>
<div style="clear:both;">
</div>
</div>
</td>
</tr>
<tr>
<td><input id="post_ids_" name="post_ids[]" type="checkbox" value="28" /></td>
<td>New Post...</td>
<td>16 Nov 01:09</td>
<td>guitarjoe02#email.com</td>
<td>guitarjoe02#email.com</td>
<td>Alaska</td>
<td>Anchorage</td>
<td>14 Jan</td>
<td>
<div>
<div class="dark" style="float:left;">
Edit
</div>
<div style="float:left;">
<form action="/posts/28" class="button_to" method="post"><div><input name="_method" type="hidden" value="delete" /><input class="btn btn-mini btn-danger" data-confirm="Are you sure?" type="submit" value="Delete" /><input name="authenticity_token" type="hidden" value="pwTuSXar01OT26FHf1bMyxKsSQ7MHWn/u3BQ9PmffS4=" /></div></form>
</div>
<div class="dark" style="float:left;">
Publish
</div>
<div style="clear:both;">
</div>
</div>
</td>
</tr>
</tbody>
</table>
<input name="commit" type="submit" value="Save changes" />
</form>
Any ideas?
Ah ha! The culprit is your button_to calls. Check out the documentation for button_to. As you will see, that helper wraps itself in a mini HTML form. In your case, its creating a form within a form, which is invalid.
You should be able to do the exact same action using link_to instead. So your button_to will end up looking like this:
<%= link_to 'Delete', post_path(post), :method => :delete, :confirm => 'Are you sure?', :class => 'btn btn-mini btn-danger' %>
Try that and let me know if it makes a difference.
Your submit tag doesn't seem to be inside the form. That will make it not actually submit the form.
Edit: I think I might be wrong... but the dodgy indentation of your code makes it hard to tell. Can you clean up the indentation to make do/ends (and the code they contain) clearer and easy to see at a glance?