I'm currently displaying on my homepage all Current Bets (current is an option of status attribute) from all members. Here is my code:
<% #bets.where(status: "Current").each do |bet| %>
<%= bet.match_name %>
<%= bet.bet_choice %>
<% end %>
(where #bets = Bet.all in my Page controller)
What I would like to do is to display on my homepage all Current bets from members who are in the "team" (team is a boolean in User).
How can I do that?
Assuming that, you have proper associations defined in your User and Bet models.
Try something like this:
User.where(team: true).joins(:bets).where('bets.status' => 'Current')
Update_1:
I see you have a column id_user in your bets table, which should be user_id instead, assuming your associations are like: User has_many bets and Bet belongs_to User.
Update_2:
If you want all such bets and then loop through the bets collection, then you have to modify the above query little bit like this:
Bet.where(status: "Current").joins(:user).where('users.team' => 'true')
Here is the right code :
<% Bet.where(status: "Current").joins(:user).where('users.team' => 'true').each do |bet| %>
Thanks for the "joins" tip KM. It helped me well.
Related
I am very novice at Ruby and Ruby on Rails.
I am trying to update a web application that has signed up volunteers that require approval before they can access full website functionality. I added a boolean field to the volunteers database model called :approved that defaults to false when a volunteer signs up, and requires a logged in administrator to update it to true.
I created an administrator class in my project that can view a list of pending volunteers from the controller:
def view_pending_volunteers
#navbar = true
#volunteers = Volunteer.where(approved: false)
end
In the administrator view I want to use checkboxes associated with volunteer, which when submitted will allow the administrator to update the :approved field in the volunteer table.
I have several issues that are not clear to accomplish this task:
In my administrator model I use has_many :volunteers with a migration that put the volunteer_id as a foreign key in the administrator database table. Is that sufficient to accomplish the task at hand, or do I need to create a join table for :approved? I can't have volunteers belong_to :administrators because they would not be able to sign up on their own, they need to be created by administrators.
I am not sure exactly how to configure the code for checkbox helpers in my administrator view. I am using form_with but I am sure my code is not correct. I would like to pass an array of parameters for each check_box associated with the :approved field for the list of pending volunteers back to the controller.
<p><b style="color:blue;font-size:24px;">
<%= form_with(model: #volunteer, local: true) do |f| %>
<% #volunteers.each do |v| %>
<li>
Volunteer: <%= x.first_name%> <%= x.last_name%> Age: <%= x.age%> Description: <%= x.description%>
<%= f.check_box (#volunteers, v.approved, options = {}, checked_value = "1", unchecked_value = "0")%>
</li>
<% end %>
<%= f.submit "Approve" %>
<% end %>
</b></p>
I am not exactly sure how to handle the array of checkbox values that get returned to the administrator controller in order to update the volunteer database table. Do I need to create a hash in the view (how to do that?) and then loop through the hash to update_attribute(:approved, true) for each checked volunteer? I have created an update_pending_volunteers method in the administrator controller for the POST operation, but am unclear on the code that should be there because I am unsure the checkbox approach.
Thanks in advance for your patience with a newbie. This seems like such a simple thing to do but I am not sure of the proper approach. I have spent quite a bit of time reviewing APIs and videos and stack overflow articles but cannot seem to piece together information that will give me confidence in a particular approach to do this correctly. Again it seems like such a simple thing to accomplish but has become a source of frustration.
See the comment from Rockwell Rice. Don't create a relationship of any kind for this functionality.
Use the URL feature of form_with, not model. You're not acting on one volunteer, you're acting on many. Create a post route (ie. approve_volunteers). In the view you would create the checkboxes like this:
<%= form_with(url: approve_volunteers_path, local: true) do |f| %>
<% #volunteers.each do |v| %>
<div class="field">
<label class="checkbox">
Volunteer: <%= x.first_name%> <%= x.last_name%> Age: <%= x.age%> Description: <%= x.description%>
<input type="checkbox" name="volunteers[]" value="<%= v.id %>">
</label>
</div>
<% end %>
<%= f.submit "Approve" %>
<% end %>
That should send params through the form like {"volunteers" => ["1", "3"]} and leave the rest empty. You might have to play around with those a little. Check your console for the params.
Then in your controller something like:
def approve_volunteers
volunteer_ids = []
volunteers = Volunteer.where(approved: false)
volunteers.each do |v|
if v.id.in?(params[:volunteers])
volunteer_ids << v.id
end
end
Volunteer.where('id IN (?)', volunteer_ids).update(approved: true)
end
See above.
The checkbox code provided by Sam worked perfectly. My url for the view is "update_pending_volunteers_path." I need to improve the formatting a little bit.
The code in the controller that worked to loop through the array of volunteer ids that was passed back into the controller is as below:
def view_pending_volunteers
#navbar = true
#volunteers = Volunteer.where(approved: false)
end
def update_pending_volunteers
#navbar = true
params[:volunteers].each do |value|
Volunteer.find(Integer(value)).update(approved: true)
end
redirect_to (administrator_dashboard_path)
end
The volunteers passed into the view have already been parsed to just those that have not been approved, so the volunteer_ids returned as checked are only from that list.
So in my application I have the models People and Outfits. In my show controller for people, I get the list like this:
#people = Person.where("description LIKE ?", "%#{params[:description]}%")
And in my view I show the outfits of each person like this:
<% #people.each do |person| %>
<p> Name: <%= person.name %> </p>
<% #outfits = person.outfits %>
<% #outfits.each do |outfit|
<p> Name: <%= outfit.name %> </p>
<p> Description: <%= outfit.description %> </p>
<% end %>
<% end %>
But loading the outfits for each person, as I load many people on the page, takes too long. Is there some way I can inherit the outfits of each person so I don't have to wait so long for the page to load? Or is the only way to speed this up to make an index between outfits and people? Thanks for any help
Use a join to load the associated records:
#people = Person.eager_load(:outfits)
.where("description LIKE ?", "%#{params[:description]}%")
.limit(20) # optional
Otherwise you have what is called a N+1 query issue where each iteration through #people will cause a separate database query to fetch outfits.
And yes the outfits.person_id or whatever column that creates the association should have a foreign key index. Using the belongs_to or references macro in the migration will do this by default:
create_table :outfits do |t|
t.belongs_to :person, foreign_key: true
end
Active Record Query Interface - Eager Loading Associations
Making sense of ActiveRecord joins, includes, preload, and eager_load
you should set a limit like this:
#people = Person.where("description LIKE ?", "%#{params[:description]}%").limit(20)
change the number according to your preference.
You can use .joins or .includes
If you have a table full of Person and you use a :joins => outfits to pull in all the outfit information for sorting purposes, etc it will work fine and take less time than :include, but say you want to display the Person along with the outfit name, description, etc. To get the information using :joins, it will have to make separate SQL queries for each user it fetches, whereas if you used :include this information is ready for use.
Solution
Person.includes(:outfits).where("description LIKE ?", "%#{params[:description]}%")
Is it somehow possible to filter database records site wide? My models are league, match, team, player and detail. Now I would like when I enter the site and select a league that everything on the site is only displaying data for this specific league.
My relations are:
league has_many matches
match belongs_to team1
match belongs_to team2
team has_many players
player has_many details
Would that be possible?
You could do it like this:
Principle
If the league option is going to be the main decider of the content on your app, you might want to design around the league model
To do this, you'd make your root the league controller, and then show data based on the league's associated content
I.E instead of Team.joins(:league).where(league: "x"), you would do:
#Leagues
league = League.find(x)
league.matches
This would mean you could load the league directly from the database, making it much simpler for the user
Nested Resources
The alternative to this is to use the nested resources method that Michael Szyndel recommended in his comment. This would make it so you'd have to visit the URLs as follows:
domain.com/leagues/1/matches/2/teams/1
The benefit of this would be to DRY up your code, but it would add lots of extra levels to your system, which you may not want. I'll give an overview of what I'd look at below:
Code
#config/routes.rb
root to: "leagues#index"
#app/controllers/leagues_controller.rb
def index
league = params[:league] ? params[:league] : "0"
#league = League.find(league)
end
#app/views/league/index.html.erb
<%= form_tag('/') do %>
<%= select_tag 'league', options_for_select(League.all.collect {|u| [u.name, u.id] }) %>
<% end %>
<% #league.matches.each do |match| %>
<%= "#{match.team_1.name} vs #{match.team_2.name} : #{match.created_at}" %>
<% end %>
This would need to be re-factored & extended to include match details, make the "league" a session variable etc, but as the question might be closed, I thought I'd give you some ideas
The bottom line is that it comes down to how you want the app to function
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?
I'm creating an application that tracks users and achievements (think, xbox live, etc.) These tables are linked via a join table. I would like to have a search form on my index that lets users type in a users name and a new page is loaded with a list of all achievements that user has earned. I'm not entirely sure how to set up this search form, on the index, to actually search the user table and return the results on a new page. Any help would be greatly appreciated. If you require more information then I'll be happy to provide it.
Here's a bit of skeleton code to get you started based off what I think you need from what you have said. I hope this is useful.
For the search bit you could do something like this in your index view:
<%= form_for User.new, :url => "search" do |f| %>
<%= f.label :name %>
<%- f.text_field :name %>
<%- end %>
In your controller:
def search
q = params[:user][:name]
#users = User.find(:all, :conditions => ["name LIKE %?%",q])
end
and in your search view:
<%-#users.each do |user| %>
Name: <%=user.name %>
<%- user.achievements.each do |achievement| %>
<%= achievement.name %>
<%- end %>
<%- end %>
You would, of course, need to ensure the users and achievement models are correctly linked:
class User << ActiveRecord::Base
has_many :achievements
end
There are plenty of tutorials and things about this e.g.:
http://blog.devinterface.com/2010/05/how-to-model-a-custom-search-form-in-rails/
Look the thing is every basic explanation in Rails3 starting with the Initial Tutorial provided by them explains you how to setup a new Controller/Model. The example was only one of thousands explaining the same problem.
It is a very broad range of different things you can do to achieve this. Basically you have to put some code in the controller:
which handles the search (including the activerecord stuff or whichever technique you use to access your model)
which sets some variables necessary for the search form
Setup two routes etc... Its to broad and completely covered even by the basic official rails3 tutorial.
Here is an application based on searchlogic is very useful and you can search by whatever you want
https://github.com/railscasts/176-searchlogic
You may want to check out the Ransack gem. https://github.com/activerecord-hackery/ransack