Rails - Sortable and Highlighted Columns - ruby-on-rails

I am trying to highlight a column title in Rails, I have followed the following tutorial to create ascending and descending sortable columns (http://railscasts.com/episodes/228-sortable-table-columns). However I can't make the higlighting working.
Here is the code I ve been using :
for the view :
%table#movies<br/>
%thead<br/>
%tr<br/>
%th{:id => 'title_header'}= sortable "title", "Movie Title"<br/>
%th Rating<br/>
%th= sortable "release_date", "Release Date"<br/>
%th More Info<br/>
the application helper :
module ApplicationHelper
def sortable(column, title = nil)
title ||= column.titleize
css_class = column == sort_column ? "hilite" : nil
direction = column == sort_column && sort_direction == "asc" ? "desc" : "asc"
link_to title, {:sort => column, :direction => direction}, {:class => css_class}
end
end
the controller :
def index
#movies = Movie.order(sort_column + " " + sort_direction)
end
and
def sort_column
Movie.column_names.include?(params[:sort]) ? params[:sort] : "title"
end
def sort_direction
%w[asc desc].include?(params[:direction]) ? params[:direction] : "asc"
end
and the stylesheet :
table#movies th.hilite {
background-color: yellow;
}
I can't find whats wrong, but when I click on the header it is only sorting and not highlighting in yellow... suspect that it has something to do with the *css_class*.
Thanks for your help!!

I believe it's because the class hilite isn't on the table header(<th>) element but on the anchor (<a>) element. Therefor in order to match the element, the CSS would need to be:
table#movies th a.hilite {
background-color: yellow;
}
So you either need to fix up your CSS or fix up which element you are putting the class on.

Thansks Link, got it, had to test the sorting before runing the sortable helper :
%table#movies
%thead
%tr
%th{params[:sort] == "title" ? {:class => "hilite"} : {}, :id => "title_header"}= sortable "title", "Movie Title"
%th Rating
%th{params[:sort] == "release_date" ? {:class => "hilite"} : {}, :id => 'release_date_header'}= sortable "release_date", "Release Date"
%th More Info
Thanks all for your answers!
Benjamin

Related

Sort_by in Hash - reverse or not reverse - how?

I have the hash, below:
library = {"1"=>{"title"=>"bbb", "money"=>10}, "2"=>{"title"=>"aaa", "money"=>12}}
and my application_helper.rb:
def sortable_columns
%w[title money]
end
def sort_column
sortable_columns.include?(params[:column]) ? params[:column] : "title"
end
def sort_direction
%w[asc desc].include?(params[:direction]) ? params[:direction] : "asc"
end
def sort_link(column, title)
direction = column == sort_column && sort_direction == "asc" ? "desc" : "asc"
icon = sort_direction == "asc" ? "fa fa-arrow-down" : "fa fa-arrow-up"
icon = column == sort_column ? icon : ""
link_to "#{title} <i class='#{icon}'></i>".html_safe, {column: column, direction: direction}
end
My table in table.html.erb:
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<% sortable_columns.each do |column| %>
<th><%= sort_link column, column %></th>
<% end %>
</tr>
</thead>
<tbody>
<% library.sort_by {|k| k[1][sort_column]}.each_with_index do |data, i| %>
...
<% end %>
</tbody>
</table>
and now - after click in "title" or "money" header - table's sorting ASC. I would like it to display DESC when clicked again (with icon arrow-down). How can this be done? I thought about "reverse", after library.sort_by {|k| k[1][sort_column]}, but doesn't work.
Reverse does work:
library = {"1"=>{"title"=>"bbb", "money"=>10}, "2"=>{"title"=>"aaa", "money"=>12}}
sort_column = "money"
sort_direction = "asc"
library
.sort_by {|k| k[1][sort_column]}
.tap { |l| l.reverse! if sort_direction == "desc" }
# => [["1", {"title"=>"bbb", "money"=>10}], ["2", {"title"=>"aaa", "money"=>12}]]
sort_direction = "desc"
library
.sort_by {|k| k[1][sort_column]}
.tap { |l| l.reverse! if sort_direction == "desc" }
# => [["2", {"title"=>"aaa", "money"=>12}], ["1", {"title"=>"bbb", "money"=>10}]]
you can sory hash as per below
if sort by only title then
library.values.sort_by{|h| h["title"] }
or you want to sort by first title and second money then use
library.values.sort_by{|h| [h["title"], h["money"]] }

Railscast #228 Sortable Table Columns: doesn't change a direction

I followed Railscast's episode #228 to create a sortable table column in my app.
My issue: when I press on the column name first time - it shows orders in ascending order. Next time I click - it doesn't automatically show records in descending order; however, if I manually write desc: "http://localhost:3000/admin/users/2/records?direction=desc&sort=created_at" - it works perfectly; what's a problem?
My controller:
def records
#records = #user.records.paginate(page: params[:page], per_page: 20).order(sort_column + " " + sort_direction)
end
private
def sort_column
Record.column_names.include?(params[:sort]) ? params[:sort] : "created_at"
end
def sort_direction
%w[asc desc].include?(params[:direction]) ? params[:direction] : "asc"
end
My application_helper:
def sortable(column, title = nil)
title ||= column.titleize
css_class = column == sort_column ? "current #{sort_direction}" : nil
direction = column == sort_column && sort_direction == "asc" ? "desc" : "asc"
link_to title, {:sort => column, :direction => direction}, {:class => css_class}
end
My view:
<tr>
<th><%= sortable "created_at" %></th>
</tr>
I had to write:
direction = sort_column && sort_direction == "asc" ? "desc" : "asc"
instead of:
direction = column == sort_column && sort_direction == "asc" ? "desc" : "asc"

Sorting the table not working

Following the #240 Railscasts i have a list of names like this
arnold
Arnold
Victor
And when I order this by that method, i get this in asc
Arnold
Victor
arnold
And this in desc
arnold
Victor
Arnold
In my controller I have:
def index
#alunos = Aluno.search(params[:search]).order(sort_column + " " + sort_direction).paginate(:per_page => params[:npage], :page => params[:page])
end
def sort_column
Aluno.column_names.include?(params[:sort]) ? params[:sort] : "nome"
end
And this in my application_helper
module ApplicationHelper
def sortable(column, title = nil)
title ||= column.titleize
css_class = column == sort_column ? "current #{sort_direction}" : nil
direction = column == sort_column && sort_direction == "asc" ? "desc" : "asc"
link_to title, params.merge(:sort => column.downcase, :direction => direction, :page => nil), {:class => css_class}
end
end
And I'm getting this (desc, in this example):
There is something that i must include in my controller or models to order in case INsensitive?
--edited
Im using sqlite3
If you're using SQL as the underlying datastore, you could do
#alunos = Aluno.search(params[:search]).order("LOWER(#{sort_column}) #{sort_direction}").paginate(:per_page => params[:npage], :page => params[:page])

Sorting with clicking on a button

I have something like this:
%section
%h1= t('.MyTableData')
.row-fluid
.span8
%table.table
%thead
%tr
%th= sortable('teachers', 'teacher_name', 'true')
%th= sortable('teachers', 'teacher_score')
%th= sortable('teachers', 'specialty')
%tbody
- #teachers.each do |teacher|
%tr
%td= as_full_name(teacher[:first_name], teacher[:last_name])
%td= number_to_percentage(provider[:teacher_score], precision: 0)
%td= provider[:specialty_name]
.span2
=render partial: 'search'
So it creates a table with some columns, if I click on the column headers like teacher_name, etc it will sort the table based on that using that sortable method.
Now I want to add a simple twitter bootstrap button saying "Reset Sorting", and when I click that it should reset these sorting we have done by clicking on column headers and go and sort it only by teacher_name.
I am very new to all this and can't put these pieces of puzzle together, so I need a button, and the sort method I need there is some samples of it in that sortable methods, But can't figure out how to put all these together and solve this.
def sortable(table, column, default_column = false)
table_params = params[table] || {}
same_sort_column = same_sort_column(table_params, column, default_column)
current_sort_direction = sort_direction(table_params)
new_direction = same_sort_column && current_sort_direction == 'asc' ? 'desc' : 'asc'
link_to(t(".#{column}"), params.merge(table => { sort_column: column, sort_direction: new_direction }))
end
= link_to 'Reset sorting', params.merge(:teachers => {:sort_column => 'teacher_name', :sort_direction => 'asc'}), :class => 'btn'

will_paginate ordering - some columns default ASC, some DESC

I have the following in a controller to enable will_paginate sorting:
def sort_column
['name', 'scheduled', 'status'].include?(params[:sort]) ? params[:sort] : "scheduled"
end
def sort_direction
%w[asc desc].include?(params[:direction]) ? params[:direction] : "desc"
end
These are supplemented by <%= sortable "status", "Status" %> at the top of a table column - clicking this will sort the table.
How can I make some columns default to ASC and some default to DESC?
Rationale
A text-based column works very well under ASC sorting. However, where I have columns with percentages or numbers, sometimes I want to show the best/highest first instead of requiring that the user click twice to get the column sorted the way they want.
Define a hash with the default sortings, grab the non-set sorting from there:
def sort_direction
sort_defaults = { 'name' => 'asc', 'age' => 'desc', 'scheduled' => 'asc' }
sort_defaults.has_value?(params[:direction]) ? params[:direction] : sort_defaults[sort_column]
end
Figured it out!
This was the original application_helper.rb code from Railscasts #228 and #240.
def sortable(column, title = nil)
title ||= column.titleize
css_class = column == sort_column ? "current #{sort_direction}" : nil
if direction == "desc"
direction = column == sort_column && sort_direction == "desc" ? "asc" : "desc"
else
direction = column == sort_column && sort_direction == "asc" ? "desc" : "asc"
end
link_to title, params.merge(:sort => column, :direction => direction, :page => nil), {:class => css_class}
end
I changed it to (changes on lines 1 and 4):
def sortable(column, title = nil, direction = nil)
title ||= column.titleize
css_class = column == sort_column ? "current #{sort_direction}" : nil
direction ||= column == sort_column && sort_direction == "asc" ? "desc" : "asc"
link_to title, params.merge(:sort => column, :direction => direction, :page => nil), {:class => css_class}
end
This enables me to now specify a default direction in a column heading:
<div class="col>
<%= sortable "priority_number", "Priority", "desc" %>
</div>

Resources