Reputation: 2482
I have a model that I call "Idee" and I want to order this model by date and popularity (there is a voting system for that). I have followed this railcast. And it works but only for the date, the votes are stored in the Vote table, here is my association:
Vote
belongs_to :idee
belongs_to :user
User has_many :votes, dependent: :destroy
Idee has_many :votes, dependent: :destroy
And I don't know how can I say that the Idee are order by vote because the count of vote is made on the Vote table and not in Idee so if I said to sort by vote he want to find a column vote in my Idee. So here is what I have done for now :
Application Helper
def sortable(column, title = nil)
title ||= column.titleize
direction = (column == params[:sort] && params[:direction] == "asc") ? "desc" : "asc"
link_to title, :sort => column, :direction => direction
end
Controller
def publiee
@idees = Idee.order(sort_column + " " + sort_direction)
@activites = Activite.all
end
private
def sort_column
params[:sort] || "created_at"
end
def sort_direction
params[:direction] || "asc"
end
View
<%= sortable "created_at", "Date" %>
Is there a way to do what I want with what I've done for now ?
PS: My "Idee" are not display in a <table>
Upvotes: 1
Views: 77
Reputation: 16022
in Idee
model class:
scope :with_votes_count, -> { select("idees.*, count(votes.id) as votes_count").references(:votes).includes(:votes).group('idees.id') }
then in controller:
def publiee
@idees = Idee.with_votes_count.order("#{sort_column} #{sort_direction}")
@activites = Activite.all
end
private
def sort_column
column = params[:sort] || 'created_at'
Idee.columns.include?(column) ? column : "created_at"
end
Now, all you have to do is pass sort_column
as "votes_count
" and sort_direction
as "DESC
" or "ASC
" as you wish to make it work.
Upvotes: 0
Reputation: 118299
Do use joins
.
def publiee
@idees = Idee.order_idess_by_votes sort_column, sort_direction
@activites = Activite.all
end
Idee
model the below code should goscope :order_idess_by_votes, ->(sort_column, direction) { joins(:votes).order("#{order_expr(sort_column, direction)}, COUNT(votes.id) DESC)") }
private
def order_expr sort_column, direction
# list all possible columns that you want to use in ORDER clause
# to SQL
order_mappings = {
'first_name_asc' => 'first_name ASC',
'first_name_desc' => 'first_name DESC',
'created_at_asc' => 'created_at ASC',
'created_at_desc' => 'created_at DESC',
# .....
}
order_mappings["#{sort_column}_{direction}"]
end
Upvotes: 2