I have a domain model which includes a triple join very similar to this: Triple join in Ruby on Rails
I have implemented the models as suggested by the accepted answer, however I'm struggling to implement a form for populating the groups table.
My form needs to provide a way to assign multiple memberships to the group. The design I am working with achieves this with sets of two select boxes, one for a user and one for a role. I have tried adding multiple sets of select boxes with code similar to this:
<%= select 'group','users', User.all.collect {|u| [u.display_name, u.id]} %>
<%= select 'group', 'roles', Role.all.collect {|r| [r.name, r.id]} %>
<br />
<%= select 'group','users', User.all.collect {|u| [u.display_name, u.id]} %>
<%= select 'group', 'roles', Role.all.collect {|r| [r.name, r.id]} %>
However, Rails only passes the values from the last set of selects into the controller. Is there a way to create multiple instances of a join table inside a single form with multiple selects? What would the create action look like for such a form?
Related
In my view I have a form with a select
<%= label_tag("employee_names", "Employees") %>
<%= select_tag("employee_names", params[:employee_names]) %>
And then I have a bunch of users, these users have a name user.name and an id user.id.
I have a method in the controller that when given the user id, narrows my list down to a specific users objects.
if params[:employee_names].present?
#time_sheets = #time_sheets.joins(:user).where("users.id IN (?)", params[:employee_names])
end
So what I am having an issue with, is I am not sure how to populate my select box with a list of users names. And then when submitted I need it to give the users id to that method. What is the best way of doing this?
I think options_from_collection_for_select should do the trick for you.
More here: http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-options_from_collection_for_select
select_tag :employees, options_from_collection_for_select(#employees, 'id', 'name')
You're looking for collection_select.
<%= collection_select(:employee, :employee_id, #time_sheets, :id, 'Employees') %>
I have a list of things users have created, and I am having trouble showing them based on who created them.
In my view I have
<%= form_tag({}, class: "form-inline") do %>
<%= label_tag("user_names", "Users") %>
<%= text_field_tag("user_names", params[:user_names]) %>
And then in my controller I am trying to scope it with this
if params[:user_names].present?
#random = #random.where(:user_id => :user_names)
I see the dropdown, but I'm trying to get is so the dropdown shows the users names and lets me select one, so that when I submit the form, I only see entries associated with that user.
What am I missing?
You need to find the users by username and join in the other model through the user association.
if params[:user_names].present?
#random = #random.joins(:user).where("users.username IN (?)", params[:usernames])
end
I have an object called a device that is associated with a customer. Once the customer orders a device, then the factory assigns the device to the customer, and the customer registers the device, and communication between the device and the rest of its associated functions can begin.
When I display the edit page to the factory administrator via the following:
<%= form_for #device do |f| %>
<%= render 'fields', f: f %>
The 'customer' field, which is itself defined in its own table, appears properly as a select dropdown. However, the default value for that select is not the currently assigned customer, but is just the current customer in the list. Is there a way using the above default rendering scheme to make the select dropdown use the current value for the device?
I've tried several variations on the theme:
<%= form_for #device do |f| %>
<%= render 'fields', f: f %>
<%= f.select :customer, options_for_select(#customers.each{|p| [p.name, p.id]}, #device.customer.name)%>
but these approaches just result in one gigantic dropdown that runs the entire width of the screen and, even then, does not show the appropriate default value. In addition, the f.select just shows the object ID of the customer, rather than the name itself.
From Rails api doc:
Given a container where the elements respond to first and last (such
as a two-element array), the “lasts” serve as option values and the
“firsts” as option text... If selected is specified, the matching
“last” or element will get the selected option-tag.
According to this:
<%= f.select :customer, options_for_select(#customers.map{|p| [p.name, p.id]}, #device.customer.id)%>
You have to set the selected option to the id (the "last" of your array [name, id]): #device.customer.id and use map.
Hope this helps!
How to read values from checkbox in rails.
Suppose I have brands and products.Under brands table, I have 3 brands say nike,reebok and puma. When none of the check box is selected It should display all the products say shirts,trousers,skirts. If nike brand is selected then should display onlt nike related products.Also user should have access to select more than 1 brands and we should able to display corresponding product details.
Conceptually what you are doing is a lot like creating a form that acts as a search engine (Ryan Bates does great screen casts and can help get you if you get lost http://railscasts.com/episodes/37-simple-search-form). Instead of entering text, the form uses checkboxes to create an array of brands the user wants to see.
First Create the form
<%= form_tag your_path_here_path, method: :get do %>
<%= label_tag :Nike %>
<%= check_box_tag 'brands[]', '1' #assuming 1 is the id of the Nike brand%>
<%= label_tag :Reebok %>
<%= check_box_tag 'brands[]', '2'%>
<%= label_tag :Puma %>
<%= check_box_tag 'brands[]', '3'%>
<%= submit_tag 'Get Products'%>
<%- end %>
Then in the controller processing this request search for the products that match brands in the form like this
Products.where('brand_id IN (?)', params[:brands])
To go a bit further. People use JS for these types of problems so that as the user checks different brands the products will automatically reload on the page without the user having to hit a submit button.
This could be accomplished by writing a JQuery function that listens to check events on your brands checkboxes and then
1) makes an Ajax call in the background to get all the relevant
products
2) Removes all the products you don't currently need on the page
3) Shows all the new products.
If you don't know any JQuery this project could be an interesting way to get started learning. Again, railscasts can help http://railscasts.com/episodes/136-jquery
In a view that I have, I am using fields_for to display form data for a relational table. However, part of this form will have select lists to choose from. I see there are label, text_field, text_area helpers for the form_for and fields_for helpers that will fill in the info needed from an already populated model object... but what about a select list helper that will do the same?
This would be particularly useful for when I have a one-to-many relationship since fields_for iterates through each item that is already in the model object and displays it with an index.
Does anything like this exist?
There are several select helper methods which you can use. The most common being collection_select. This is great if you have a belongs_to association on the model and you want to use a select menu to set this.
<%= f.collection_select :category_id, Category.all, :id, :name %>
For other situations there is the more generic select method. Here you can supply an array of options you want to provide.
<%= f.select :priority, [["Low", 1], ["Medium", 2], ["High", 3]] %>
The first value in each array element is the name of the select option, the second is the value which will be assigned to the attribute.
There are many other select menus (for dates and times) but the above two should cover most situations. These methods work on both form_for or fields_for.
You are looking for select or collection_select. Both can be used in form_for or fields_for blocks. There are examples on how to use them in a form_for in the documentation