I'm working on an app in Rails that has teacher and student users. I want to list all the users that belong to a teacher and then let the teacher select a student to send a message to. I have a message model that has :content and :user_id for params. I want to set the :user_id based on the student selected. Here is my code:
<% #students = Student.all %>
<% #students.each do |student| %>
<% if student[:teacher_id] == #current_user.id %>
<%= radio_button 'student', 'id', student.id %>
<%= student.name %>
<% #current_student = Student.find(student.id) %>
<% end %>
<% end %>
<%= form_for Message.new do |f| %>
<%= f.text_area :content, class: 'messageTextarea' %> <br>
<%= f.hidden_field :user_id, :value => #current_student.id %>
<%= f.submit %>
<% end %>
So, I am looping through all students and printing those that have the same ID as the current user (the teacher) with a radio button. The radio button's value is the student's id. Then I want to pass that value to the :user_id of the message so it will then be retrievable for the student's view.
Currently, this code always passes in the value of the last student listed rather than the student selected. How can I change
<% #current_student = Student.find(student.id) %>
to find the student selected rather than the last one?
I did test this code using
<%= f.hidden_field :user_id, :value => #current_user.id %>
and that did work, but I don't want the current_user's id, of course. Thanks for any help!
If you want one form with radio buttons for the students, You gonna need a little bit JavaScript(Or Jquery), All you have to do is to put a listener on these radio button and when user click on one of them you change the hidden input of user_id name.
User example in this link will help you to put listener on a bunch of radio buttons and change another field value, it will be something like this:
$('input[type=radio][name=student[id]]').change(function() {
$('#user_id').val($(this).val());
});
all you have to do is to make sure of name=student[id] and #user_id, if you used this approach you won't need this line anymore:
<% #current_student = Student.find(student.id) %>
Hope it works.
Related
I have a model like:
class User < ActiveRecord::Base
enum :status [:banned, :registered, :trial, :pending]
end
On my edit page, I want to show a list of 4 radio buttons and pre-select the radio button that is currently set for a user.
How can I do this?
<%= form_for #user do |f| %>
<%= f.collection_radio_buttons :status, User.statuses, :first, :first %>
<%= f.submit %>
<% end %>
Ref
Rails creates a class method using the pluralized attribute name when you use enum. The method returns a key value pair of strings you've defined and what integers they map to. So, you could do something like this:
<% User.status.keys.each do |status| %>
<%= f.radio_button :status, status %>
<%= f.label status.to_sym %>
<% end %>
I'm new to Ruby on Rails. There are two models in my project: room and guest. The association is "room has_many guests" and "guest belongs to room".
I have separated views for manage rooms and guests. Rooms don't require "guests" value on creation. However, I want to create new guests and assign it to certain room at the same time. What will be the proper way to do it? How do I transfer the input from web and match the entities in database.
The code is pretty much the same as "Getting Started with Rails". In the tutorial, they add "comments" in the "article" view and use "comment" as a sub-resource of "article". In my case, I treat the two models equally and want to manage them in separated views.
Update:
I used the collection_select and try to work with my guest_controller.
<%= form_for :guest, url: guests_path do |f| %>
<% if #guest.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(#guest.errors.count, "error") %> prohibited this guest from being added:
</h2>
<ul>
<% #guest.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :name %><br>
<%= f.text_field :name %>
</p>
<p>
<%= f.label :phone %><br>
<%= f.text_field :phone %>
</p>
<p>
<%= f.label :room%><br>
<%= f.text_field :room %>
</p>
<p>
<%= f.label :room %><br>
<%= f.collection_select(:room_id, Room.all, :id, :title) %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
<%= link_to 'Back', guests_path %>
In my guest_controller, the create method called by the form above is :
def create
#guest = Guest.new(guest_params)
#guest.room = Room.find(params[:room_id])
if #guest.save
redirect_to #guest
else
render 'new'
end
end
However, when I create a new guest, it shows that:
ActiveRecord::RecordNotFound in GuestsController#create
Couldn't find Room with 'id'=
I checked that room_id=4 and Room.find(4) return the proper room.
What's wrong?
If you want to select one room from those that exist, use collection_select form helper, here is a relevant snippet from the docs:
f.collection_select(:city_id, City.all, :id, :name)
This outputs a dropdown list that:
fills in city_id parameter in this context
uses City.all for filling in the options in the list (I will be referring to "each" city as city)
uses city.id as data (that gets sent in the form)
shows city.name for each city in the dropdown list (hopefully, human-readable)
Bear in mind though, that in terms of security it's like "look, you can select this, and this and this!", that does not prevent users from selecting an unlisted option: either by modifying form markup by hand or sending handcrafted queries.
So should you ever be limiting access to specific rooms, and list only Room.unlocked (unlocked assumed a scope), make sure the received room_id refers to a room from that scope as well. Most of these problems are dealt with using either validations or careful association management (Room.unlocked.find_by_id(:room_id) that outputs nil if the room is not in that scope).
UPD: as for the latest problem you're having -- your understanding on how the form contents look in params seems to be wrong. It's quite a common misconception actually.
form_for :guest will construct a separate object/hash in params[:guest], with all the form's fields inside it. So it actually is inside params[:guest][:room_id], but no, don't rush with adding the missing part.
You've already built a #guest object from entire params[:guest], so if the room actually exists, it's inside #guest.room already and can be validated inside the model during save. Have a look at Rails validators.
Take a look at the fields_for tag:
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-fields_for
It allows just that, to create a guest while creating a room and associating each other.
I have a table: family_children (the model is family_child) where family has many children.
I get the children like this:
#family_children = #family.children
where .children is an association to family_children table.
In a view I want to iterate through the children, and put each of them in a text_field. Of course, I need these fields as params when the page is POSTing. I.e. I think that I should get the children as an array.
How can I achieve that?
I mean, if I'll write
<%= text_field 'child', 'name' %>
I don't really get what I need.
Try something like this in your view:
<% #family_children.each_with_index do |c, i| %>
<%= text_field_tag "children[#{i}]", c.name %>
<br />
<% end %>
This should return params[:children] after posting which should be an array. I wasn't sure of the name of the property you want to show in the text box so I have assumed it is called 'name'.
Actually, #family_children object acts as array, so you can simply call each or map on it.
Do you want to put the children's names in a form field or in the view as just a part of the page text? could you include the view file?
since u want the family_children data to be POSTed, u need to see the concept of nested attributes. please see http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html and http://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for
class Family
has_many :children, :class => "FamilyChild"
accepts_nested_attributes_for :children
end
class FamilyChild
belongs_to :family
end
and the form can be as
<%= form_for #family do |p| %>
First name: <%= p.text_field :first_name %>
Last name : <%= p.text_field :last_name %>
<%= fields_for #family.children do |c| %>
<%= c.text_field :child_name %>
<% end %>
<%= f.submit %>
<% end %>
I have a Task model, which is joined in a many-to-many relationship with an Objective model.
I have a Task edit form where a user can associate any Objective with a Task via checkboxes. When a checkbox is checked, it should indicate an association between the Task and a particular Objective; when a checkbox is not checked, there should be no association. This should be persisted to the database when the form submits.
<%= form_for #task do |f| %>
<% Objective.all.each do |objective| %>
<%= check_box_tag :objective_ids, objective.id, #task.objectives.include?(objective), :name => 'task[objective_ids][]' %>
<% end %>
<%= f.button :submit %>
<% end %>
Updating a Task seems to work absolutely fine as long as one checkbox is checked by the user, but when the user does not check any checkboxes, the :objective_ids param (which is an array of Objective ids) is not included in the POST action at all. Because of this, when I do #task.update_attributes(params[:task]) in the controller, the Task's collection of Objectives is not updated (i.e. the Task should no longer have any Objectives associated with it, because no checkboxes were checked).
So how can I ensure the :objective_ids param is included in the POST, even if only as an empty array?
Add hidden field above all checkboxes with empty value. It will be sent in case user didn't check any checkboxes.
<%= form_for #task do |f| %>
<%= hidden_field_tag "task[objective_ids][]", nil %>
<% Objective.all.each do |objective| %>
<%= check_box_tag :objective_ids, objective.id, #task.objectives.include?(objective), :name => 'task[objective_ids][]' %>
<% end %>
<%= f.button :submit %>
<% end %>
Here is a good railscasts about this.
You may also want to check the source code for it.
Asked similar before.
Rails 3 has_many :through Form
But can't get the relationship with employmentships to be created from the users form.
Have read http://www.justinball.com/2008/07/03/checkbox-list-in-ruby-on-rails-using-habtm/
and http://millarian.com/programming/ruby-on-rails/quick-tip-has_many-through-checkboxes/ (which I was really hoping that it worked.)
Form submits, but only creates a blank record in employmentship.
<%= form_for #user do |f| %>
...
<p>
<% Company.all.each do |company| %>
<%= check_box_tag :company_ids, company.id, #user.companies.include?(company), :name => 'user[company_ids][]' -%>
<%= label_tag :companies_ids, company.id %>
<% end %>
</p>
<p><%= f.submit %></p>
<% end %>
Include a hidden field tag in the form to make sure something gets submitted when none of the check boxes are selected. This should work, after the <%end%>:
<%= hidden_field_tag "user[company_ids][]" %>
I may be wrong, but I think that the first arg of the check_box_tag function is the actual name of the input, so instead of
check_box_tag :company_ids, company.id, #user.companies.include?(company), :name => 'user[company_ids]'
you could try something like
check_box_tag 'user[company_ids]', company.id, #user.company_ids.include?(company.id)
Let me know if it works!