Populate a select box with user names - ruby-on-rails

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') %>

Related

Select multiple values from associated model rails

Assuming I have this association
User have_many posts
Post belongs_to user
User Post
----------------
id id
name title
user_id
How to list only post title and username with includes/joins ?
(list of posts [title - username])
#posts = Post.includes(:user).select('........')
don't offer this
#posts = Post.all.each {|p| p.user.username}
__________________UP_____________________
It worked for joining 2 tables.
What if I want to use it for more complex example?
check out my prev question optimize sql query rails
#Humza's answer partly worked.
it might be something like this
#posts = Post.joins(:user, :category).paginate(:page => params[:page]).order("created_at DESC")
but It doesn't display posts that don't have category
I also need to display gravatar but I think I can just use user.email as usr_email and use gravatar_for (post.usr_email) but I'll have to customize gravatar helper for this.
posts_controller.rb
def index
#posts = Post.includes(:user).includes(:comments).paginate(:page => params[:page]).order("created_at DESC")
end
index.html.erb
<%= render #posts %>
_post.html.erb
<%= gravatar_for post.user, size:20 %>
<%= link_to "#{post.title}", post_path(post) %>
<%= time_ago_in_words(post.created_at) %>
<%= post.comments.count %>
<%= post.category.name if post.category %>
Take a look at pluck.
Post.joins(:user).pluck(:title, :name)
Note that it works in this case because there's no ambiguity regarding the name column, you might want to specify the table explicitly (pluck(:title, "users.name")).
includes is used in case of eager-loading. You need joins in this case.
posts = Post.joins(:user).select("posts.title AS title, users.name AS username")
You can access the values then in the following way:
post = posts.first
post.title # will give the title of the post
post.username # will give the name of the user that this post belongs to
If you can pluck multiple columns, then the following might be more useful to you:
posts = Post.joins(:user).pluck("posts.title", "users.name")
The result will be a 2D array, with each element being an array of the form [post_title, post_username]
Post.joins(:user, :category)
but It doesn't display posts that don't have category
That's because joins uses INNER JOIN to join the tables together. If you want to everything from Post even though the particular record doesn't have its counterpart in the other table, you need to use LEFT JOIN. Unfortunately ActiveRecord doesn't have a nice way of generating it and you will need to do that manually:
Post.joins("LEFT OUTER JOIN categories ON categories.post_id = posts.id")...
See A Visual Explanation of SQL Joins for more information.
You can call array methods on a scope so:
Post.includes(:user).map { |p| [p.title, p.user.name] }
will get the posts with included user and map each post to a tuple of the post title and the user name.
That may not entirely answer your question as I think you might want to restrict the results of the query to just the required fields in which case, I think you can add a .select('title', 'users.name') to the query. (Not in a position to test at the moment)

Showing only things belonging to a selected user

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

Using collection_select for Searching In Active Record - Rails 3.2.9

I have only used collection_select once to populate a country id on an associated model User. Now I would like to do a search of User using the same collection_select statement on another view and list the Users for a selected country. My attempts have failed. I can look at the link after a country is selected and see that the id for the country is selected. But when I click my submit button the collection_select statement resets the selected value to the default selected value and ignores the value selected. For example when I select the country of France, the id is 75. When I select France and click Search by Country the id shows up like this.
http://localhost:3000/users_admin?utf8=✓&query=&user%5Bcountry_id%5D=75
Here is the form where I have the collection_select statement. I copied the statement that I am successfully using when I add/update a record on the User model with the selected country_id. What I want my logic to do is when I select a country and click Search by Country that the selected country remains selected in the drop down list and the User records with the selected country_id are displayed on the screen. The Search by Name works as expected.
<%= form_tag users_admin_path, method: 'get' do %>
<p style="padding-left: 20px;">
<%= text_field_tag :query, params[:query], placeholder: "Search for first, last or full name" %>
<span valign="center"><%= submit_tag "Search by Name", class: "btn btn-medium btn-custom", :name => nil %></span>
<%= collection_select(:user, :country_id, Country.order('name'), :id, :name, {:selected => 233}) %>
<span valign="center"><%= submit_tag "Search by Country", class: "btn btn-medium btn-custom", :name => nil %>
</p>
<% end %>
Here is the code in my controller.
def users_admin
case
when User.where("active_user = ?", '1').count > 0 # blocked users exist
#users = User.where("active_user = ?", '1').all
when params[:commit]=='Search by Country'
#users = User.where("country_id = ?", params[:country_id]).all
else
#users = User.text_search(params[:query])
end
#microposts = Micropost.all
end
I'm not sure if the issue is with how the collection_select statement is coded or another logic problem. My first thought was that I need to somehow save the selected value from the collection_select statement then use it in my where clause. But I do not know how to recode the statement to do that and also have the default selected value as 233 which is the United States when the screen is first displayed. I also thought that maybe I should have two different forms instead of one. I just do not know the direction I should go at this point.
I have searched mainly Stack Overflow for questions regarding this issue. The questions related to collection_select for the most part were relating to uses that are way past what I will probably ever use it for. Again I have only used the collection_statement once:)
Any help will be appreciated.
collection_select should be used when you are working with a model in your form (i.e. when you use form_for #user do, not form_tag
Try something like this:
<%= select_tag :country_id, options_from_collection_for_select(Country.all, :id, :title, params[:country_id]), include_blank: true %>
The params[:country_id] parameter there makes sure that whatever country_id is passed in via the GET request will be selected in your dropdown after the user submits your search form.
btw, form_for is used when there is a model involved (being created/updated). If you're creating a search form, this isn't the case and you should be using form_tag
Read this for more information: http://guides.rubyonrails.org/form_helpers.html#making-select-boxes-with-ease
After doing more searching I decided to display params on my view just to see what was in the hash. I did not have commit in my submit_tag so I changed to check to see if params[:country_id] was present. I was able to get the country search working with the modified code:
case
when User.where("active_user = ?", '1').count > 0 # blocked users exist
#users = User.where("active_user = ?", '1').all
when params[:country_id].present?
#users = User.where("country_id = ?", params[:country_id].to_i).all
else
#users = User.text_search(params[:query])
end
The only problem I have left (minor issue) is that in order to get the name search working properly after a country search the person has to select the blank entry in the country list. Other than that this is solved. It should not take long to figure out how to wipe out the value in params[:country_id]. Either that or I may do an implicit check for params[:query].present? . Thanks for your help. Another pair of eyes did help indeed.

I want to return a single result using .find() with Ruby on Rails

I have a user view and a rental view.
In my rental view im trying to show the current users name. I think I am pretty close but I can't work out this last bit.
This returns all of my users in a select list
<%= f.select :user_id, User.find(:all).collect {|t|
[t.user_name, t.id]} %>
This returns my current users ID
<%= f.number_field :user_id %>
So I thought I could do something like
<%= f.select :user_id, User.find(:user_id).collect {|t|
[t.user_name, t.id]} %>
Which I would want to only return the current user in a select list with their id as the value and their name in the list. If I do the above it tells me
Couldn't find User with id=user_id
So user_id is being passed as a literal string but I want to pass the user_id variable which should be somthing like 10. I don't know how to pass the user_id as a variable.
I'm fairly new to ROR, I might be going about this the completely wrong way. Any help is much appreciated.
I am assuming you have a rental object, for which you show the form, I assume it is an instance variable #rental, furthermore I assume that inside your Rental class there is the following relation
class Rental
belongs_to :user
end
Then you could just write the following:
f.select :user_id, [[#rental.user.user_name, #rental.user.id]]
Hope this helps.
On a related but less important note: it is really weird to have a column called user_name for a user: I would call that column just name, since it is part of a user anyway.
find() wants a variable, not a symbol. And :all probably isn't what you want. You should write a method in your controller like:
def user(u)
#user = User.find(u)
end
Then call the method in the view or whatever like (I don't know exactly what you're trying to do here):
<% user(current_user.id) %>
Then you'll have a #user object with which you may play, i.e.:
<%= f.select :user_id, [[#user.name, #user.id]] %>
I think you should be able to do:
<%= f.select :user_id, User.find(f.object.user_id).collect {|t| [t.user_name, t.id]} %>
This does seem a little odd to me though. I'd have thought either:
Your object has a proper association to the relevant user, in which case you should be able to do f.object.user.user_name and f.object.user.id.
If you genuinely want the currently logged in user, you should probably be asking your authentication framework/code for the reference. E.g. if you were using Devise, it would be current_user.
As an aside, I don't really understand why you want a select list just containing the current user - is that definitely what you're trying to achieve, or have I misunderstood?

Rails: Populating a triple join table with select boxes

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?

Resources