June 28, 2016 • 2 min read
Recently a friend asked me a question about sorting in Rails, and I thought I’d share my answer here:
I’m working on an app that displays movies. The index page simply lists all movies in a table
%table#moviesin HAML. There is a clickable ‘Movie Title’ header above the list of movies and when clicked, the page should reload but in alphabetical order. Therefore I assume I need to use
.order(:title)somewhere in the app. I was able to simply order all movies when the page loads by doing the following in
def index @movies = Movie.all.order(:title) end
But I need it to execute when the following is clicked from the
%th= link_to('Movie Title', '/')
Here’s how I’d tackle this problem.
# app/views/movies/index.html.haml %h1= link_to 'Movie Title', root_path(sort: true)
This utilizes two Rails conventions, a named path (
root_path is synonymous
'/'), and a query string
When the link is clicked, a parameter will be appended to the URL
http://yoursite.com/?sort=true). That parameter will be available in the
controller action, and we’ll use it to sort the movies. As a side note, this detail can
be used to quickly iterate on changes, as you can type your parameters directly
into the browser address bar.
Here’s the controller code:
# app/controllers/movies_controller.rb def index @movies = Movies.all if params[:sort] @movies = @movies.order(:title) end end
This will always define
@movies as all movies, unless the query parameter
sort is true. When true, it will redefine
@movies as itself, but ordered by
This is server-side sorting, and it has many uses. The parameter could be
true, or it could be set to
director, etc., further refining
our search results.
Finally, while this solution is illustrative for homework, it’s not yet
production grade, because it introduces a security vulnerability. Right now we
are accepting any value for
sort, which exposes us to evil code injection. Rails solved this
with something called strong parameters,
an important topic beyond the scope of the problem.
Blog of Jake Worth.