I am creating a trivia game where there are multiple categories (like sports, history, art, etc.). At the end of each category's game, I want to show a scoreboard of results only for that single category.
By specifying the category in the method, I am now successfully filtering only for history scores, as seen here:
class ScoreboardController < ApplicationController
def index
#participations = Participation.where(finished: true, category: "history").order(score: :desc)
end
end
While that is good, I now need to make it so that the scoreboard controller can produce a filtered set of scores for history, sports, and any other number of category iterations, whereas it only covers the history category at current.
To make this happen, I tried creating a second method within the controller for:
#participations = Participation.where(finished: true, category: "sports").order(score: :desk)
Unfortunately, that still only returned scores from the first method for history with no sports scores.
I think I am doing one of two things wrong:
1) Am I writing the methods incorrectly by adding additional iterations into the same controller?
2) In the scoreboard view (as opposed to the scoreboard controller), I am not calling the controller correctly.
Any ideas where I am going wrong?
Additional Info: Scoreboard View
<thead>
<tr>
<th>#</th>
<th>User</th>
<th>Category</th>
<th>Score</th>
</tr>
</thead>
<tbody>
<% #participations.each_with_index do |participation, index| %>
<tr>
<td>#<%= index + 1 %></td>
<td><%= participation.user.username %></td>
<td><%= participation.category %></td>
<td><%= participation.score %></td>
</tr>
<% end %>
</tbody>
You should change your ScoreboardController index to contain different instance variables for different categories. ie:
ScoreboardController.rb
def index
#participations_score = Participation.where(finished: true, category: "history").order(score: :desc)
#participations_history = Participation.where(finished: true, category: "sports").order(score: :desc)
# other particpation categories
end
index.html.erb
<h1>History Scoreboard</h1>
<thead>
<tr>
<th>#</th>
<th>User</th>
<th>Category</th>
<th>Score</th>
</tr>
</thead>
<tbody>
<% #participations_history.each do |participation_history| %>
<tr>
<td>#<%= participation_history.id %></td>
<td><%= participation_history.username %></td>
<td><%= participation_history.category %></td>
<td><%= participation_history.score %></td>
</tr>
<% end %>
</tbody>
<!--- Add more code for the rest of the categories --->
I strongly suggest that you brush up on your knowledge of the Ruby programming language as well as the Ruby on Rails framework. You can do so by going to Code academy.
Sounds like a job for nested resources, with a singular resource for:
#config/routes.rb
resources :categories do
resource :scoreboard, module: :categories #-> url.com/categories/:category_id/scoreboard
end
#app/controllers/categories/scoreboards_controller.rb
class Categories::ScoreboardsController < ApplicationController
def show
#results = Participation.where(finished: true, category: params[;category_id]).order(score: :desc)
end
end
This will allow you to invoke the scoreboards#show action, populating with the appropriate category from the routes....
#app/controllers/categories_controller.rb
class CategoriesController < ApplicationController
def create
#category = ...
redirect_to [#category, :scoreboard]
end
end
Associations
Now, there's a better way.
Instead of calling Participation naked, you'll be best using the categories and scoreboards association you should have set up in the backend:
#app/models/category.rb
class Category < ActiveRecord::Base
has_many :participations
has_many :scoreboards, through: :participations
end
#app/models/participation.rb
class Participation < ActiveRecord::Base
belongs_to :category
belongs_to :scoreboard
end
#app/models/scoreboard.rb
class Category < ActiveRecord::Base
has_many :participations
has_many :categories, through: :participations
end
This will allow you to use the same routes as above, but this time populating the response through the associations:
#app/controllers/categories/scoreboards_controller.rb
class Categories::ScoreboardsController < ApplicationController
def show
#category = Category.find params[:id]
#results = #category.participations.where(participation: {attribute: true})
end
end
Related
I'm beginner, so sorry if i ask for something trivial.
Two tables imed_patient and imed_operator are legal Postgresql tables with relation between them (many patients to one operator by r_opr_code field in imed_patient), described by definitions:
class ImedOperator < ActiveRecord::Base
self.table_name = "imed_operator"
self.primary_key = "code"
belongs_to :ImedPatient
end
class ImedPatient < ActiveRecord::Base
self.table_name = "imed_patient"
self.primary_key = "code"
has_one :ImedOperator, :foreign_key => "r_opr_code"
end
I want to view all patients with data (ex. name, surname) from imed_operator (details of patients), so I produced pacjenci_controller.rb
class PacjenciController < ApplicationController
def index
#patients = ImedPatient.all
#operator = #patients.operators
end
def show
#patient = ImedPatient.find(params[:id])
end
end
In web broweser I receive error :
NoMethodError in PacjenciController#index
undefined method `operators' for #<ImedPatient::ActiveRecord_Relation:0x007fbb269ffe00>
Extracted source (around line #5): #operator = #patient.operators
UPDATE:
my index.html.erb
<h1>Pacjenci w Optimed</h1>
<table>
<tr>
<th>Nazwisko</th>
<th>ImiÄ™</th>
<th>Pesel</th>
<th>Code_operator</th>
<th>Wizyty</th>
<th></th>
<th></th>
</tr>
<% #patients.each do |patient| %>
<tr>
<td><%= link_to #operator.surname, controller: "pacjenci", action: "show", id: patient.r_opr_code %></td>
<td><%= #operator.first_name %></td>
<td><%= #operator.pesel %></td>
<td><%= patient.r_opr_code %></td>
<td><%= link_to 'Wizyty', url_for(action: 'wizytypacjenta', controller: 'wizyty', id: patient.code) %></td>
</tr>
<% end %>
</table>
<br>
<p><%= link_to 'Start', url_for(action: 'index', controller: 'pacjenci') %></p>
<p><%= link_to 'Wstecz', url_for(:back) %></p>
And I stucked :(
ImedPatient has_one ImedOperator, so you need to change
#operator = #patient.operators
to
#operator = #patient.imed_operator
However, I'm not sure you are doing what you want to do. In the index action you are calling ImedPatient.all, so you will get all the records. That's why the variable should be called #patients, not #patient. Then, if you want to get all operators for all the patients, you should use
#operator = #patients.map(&:imed_operator)
If you made a mistake and you actually wanted the #operator in show action it should be:
#operator = #patient.imed_operator
Update: another problem is the has_one declaration. I think it should be:
has_one :imed_operator, :foreign_key => "r_opr_code"
Update 2:
After what you have written in comments it seems that you have confused the association and it should be the other way:
class ImedOperator < ActiveRecord::Base
has_one :imed_patient, foreign_key: 'r_opr_code'
end
class ImedPatient < ActiveRecord::Base
belongs_to :imed_operator , foreign_key: 'r_opr_code'
end
Have a look at: http://guides.rubyonrails.org/association_basics.html#choosing-between-belongs-to-and-has-one
I wanna implement a order page, but it's so hard...
The system is in portugues, for others reasons, sorry about this.
My view:
conta/pedidos/index.html.erb
<h3>Meus pedidos</h3>
<table>
<thead>
<th>#</th>
<th>Data do pedido</th>
</thead>
<tbody>
<% #pedidos.each do |pedido| %>
<tr>
<td><%= link_to pedido.id, pedido_path(pedido.token) %></td>
<td><%= pedido.create_at.to_s(:long) %></td>
</tr>
<% end %>
</tbody>
</table>
My controller:
conta/pedidos_controller.rb
class Conta::PedidosController < ApplicationController
before_action :authenticate_usuario!
def index
#pedidos = current_usuario.pedidos.order("id DESC")
end
end
My model:
pedido.rb
class Pedido < ActiveRecord::Base
belongs_to :pessoa
has_many :itens, class_name: "ItemPedido" , dependent: :destroy
accepts_nested_attributes_for :enderecos
before_create :gerar_token
def gerar_token
self.token = SecureRandom.uuid
end
end
And the error:
ArgumentError in Conta::PedidosController#index
No association found for name `enderecos'. Has it been defined yet?
Please, what I make?
I'm not sure why do you have accepts_nested_attributes_for :enderecos in pedido.rb. It's not mentioned anywhere in the provided code. Can you simple comment/remove it?
If it's need, then you need to set association for it: may be has_many :enderecos
I have this code:
class Property < ActiveRecord::Base
has_many :owners, dependent: :destroy
has_many :residents, through: :owners
end
class Resident < ActiveRecord::Base
has_many :owners, dependent: :destroy
has_many :properties, through: :owners
end
class Owner < ActiveRecord::Base
belongs_to :resident
belongs_to :property
end
and default generated controllers.
I searched for how to list data from has_many through relationships and it works for me, but don't know why it also shows the whole array.
Here is the view code:
<tbody>
<% #residents.each do |resident| %>
<tr>
<td><%= resident.name %></td>
<td><%= resident.birthdate %></td>
<td><%= resident.birthId %></td>
<td><%= resident.address %></td>
<td><%= resident.email %></td>
<td><%= resident.tel %></td>
<td><%= resident.properties.each do |property| %>
<%= property.name %>
<% end %>
</td>
</tr>
<% end %>
</tbody>
and when I show the data from that iteration it shows the column, in this the "case name", and in [] the whole array like this:
Dostojevskeho 15
[#<Property id: 2, name: "Dostojevskeho 15", registerNumber: "9845", propertyList: 6977, propertyType: 8, created_at: "2016-01-09 20:20:04", updated_at: "2016-01-09 20:20:04">]
I can't find what am I doing wrong. When I compared it to all tutorials my view looks fine to me.
This is part of the residents controller with index and show:
class ResidentsController < ApplicationController
before_action :set_resident, only: [:show, :edit, :update, :destroy]
def index
#residents = Resident.all
end
def show
#residents = Resident.find(params[:id])
end
You need to change this line:
<%= resident.properties.each do |property| %>
to this:
<% resident.properties.each do |property| %>
Removing the = tells Rails that you only want to iterate over the resident.properties. Otherwise you get this weird behavior, where Rails is trying to print the iterator itself onto the page - which is rarely what you want.
Imagine the following situation:
I have a user model and a user_group model, so:
Class User < ActiveRecord::Base
belongs_to :user_group
end
Class UserGroup < ActiveRecord::Base
has_many :users
end
Now, let say some of the user does not have group. Which mean, when I call:
<% #u.each do |item| %>
<tr>
<td><%= item.id %></td>
<td><%= item.username %></td>
<td><%= item.name %></td>
<td><%= item.user_group.name %></td>
</tr>
<% end %>
It will throw nil. Is there any way nil will be displayed as empty string (somewhat like LEFT JOIN, or DataMapper include_related in CodeIgniter) instead of showing error page?
Right now I am using
<%= item.user_group.name unless item.user_group.nil? %>
to check before calling, but doing that for all view file is somewhat not a good approach.
Thanks in advance!
use try..
class Manufacturer < ActiveRecord::Base
has_many :products
def contact
"Manufacturer has been contacted."
end
end
Product.first.try(:manufacturer).try(:contact)
#=> nil
Product.last.try(:manufacturer).try(:contact)
#=> "Manufacturer has been contacted."
You can use an helper too:
def group_name_for(item)
item.user_group.name unless item.user_group.nil?
end
And call that helper in your views:
<%= group_name_for(item) %>
I have two controllers: tasks, tasksperson.
I have views/tasks/index.html.erb:
<table>
<% #tasks.group_by(&:name).each do |name, tasks| %>
<tr>
<td><%= name %></td>
<td><%= tasks.size %></td>
<td><%= tasks.select{ |task| task.done != true }.size %></td>
</tr>
<% end %>
</table>
I want to create a link in views/tasks/index.html to views/tasksperson/index.html.erb.I want also to send the name into 'index' in Tasksperson_controller.. I tried to do this by getting params[:name] but I think it's wrong
maybe, I need to do something like:
<td><%= link_to 'Show Tasks', tasksperson_path(name) %></td>
this is my tasksperson_controller:
class TaskspersonController < ApplicationController
def index
#tasks = Task.where(:name => params[:name]) respond_to do |format|
format.html # index.html.erb
format.json { render json: #tasks }
end
end
end
and views/tasksperson/index.html.erb:
<table>
<tr>
<th>Name</th>
<th>num of tasks</th>
<th>num tasks left</th>
<th>test</th>
</tr>
<% #tasks.each do |f| %>
<tr>
<td><%= f.name %></td>
<td><%= f.task %></td>
<td><%= f.done %></td>
</tr>
<% end %>
</table>
You need to add :name as a parameter to the rule that defines the route to TaskspersonController#index in routes.rb
so it would be something like this:
match 'tasksperson/index/:name' => 'tasksperson#index', as: :tasksperson_path
Based on your comment "...so Task have many taskpersons" I think you want a data model similar to below
class Task < ActiveRecord::Base
has_many :assigned_tasks
has_many :people, :through => :assigned_tasks
end
# maybe this is just the User class?
class Person < ActiveRecord::Base
has_many :assigned_tasks
has_many :tasks, :through => :assigned_tasks
end
# was TaskPerson
class AssignedTask < ActiveRecord::Base
belongs_to :task
belongs_to :person
end
See http://guides.rubyonrails.org/association_basics.html#the-has_many-through-association for information about "The has_many :through Association"
task = Task.create(:title => "Go up the hill")
jack = Person.find(00000)
jill = Person.find(00000)
task.people << jack
task.people << jill
task.assigned_tasks.each do |join|
puts join.created_at
puts join.person.name
# 0 - jack
# 1 - jill
end
task.people.each do |person|
puts person.name
end
I am not exactly sure what you are trying to display in your views, it looks like you are grouping by a task name attribute in task/index, is that the Persons name?