In this article, we will discuss an easier way to search and sort in Rails, using a gem called ransack.
First, do some basic setup:
1
2
3
4
5
rails new ransack-app
rails db:create
rails g model Author name
rails g scaffold Post title body:text author:references
rails db:migrate
In your gemfile, add:
1
2
3
# Gemfile
gem 'ransack'
Make a relation with posts in Author.
1
2
3
# app/models/author.rb
has_many :posts
Now seed in some data.
1
2
3
4
5
6
7
8
9
10
11
# db/seeds.rb
Author.create(name: 'William Shakespeare')
Author.create(name: 'George Eliot')
Post.create(title: 'Wisdom', body: 'Some are born great, some achieve greatness, and some have greatness thrust upon them.', author_id: 1)
Post.create(title: 'Wisdom', body: 'A fool thinks himself to be wise, but a wise man knows himself to be a fool.', author_id: 1)
Post.create(title: 'Love', body: 'The course of true love never did run smooth.', author_id: 1)
Post.create(title: 'Love', body: 'Blessed is the influence of one true, loving human soul on another.', author_id: 2)
Post.create(title: 'Life', body: 'The world is full of hopeful analogies and handsome, dubious eggs, called possibilities.', author_id: 2)
Post.create(title: 'Wisdom', body: 'It will never rain roses: when we want to have more roses we must plant more trees.', author_id: 2)
In app/controllers/posts_controller.rb
, update the index method.
1
2
3
4
5
6
# app/controllers/posts_controller.rb
def index
@q = Post.ransack(params[:q])
@posts = @q.result.includes(:author)
end
Now in app/views/posts/index.html.erb
, add the following form:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# app/views/posts/index.html.erb
<%= search_form_for @q do |f| %>
<%= f.label :title_cont %>
<%= f.search_field :title_cont %>
<%= f.label :body_cont %>
<%= f.search_field :body_cont %>
<%= f.label :author_name_cont %>
<%= f.search_field :author_name_cont %>
<%= f.submit %>
<% end %>
Now you will be able to search the posts by title, body text and author name.
Now, let’s jump to the second part - sorting.
In app/views/posts/index.html.erb
, update the table as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# app/views/posts/index.html.erb
<table>
<thead>
<tr>
<th><%= sort_link(@q, :title, 'Title', default_order: :desc) %></th>
<th>Body</th>
<th><%= sort_link(@q, :author_name, 'Author', default_order: :desc) %></th>
<th><%= sort_link(@q, :created_at, 'Created', default_order: :desc) %></th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% @posts.each do |post| %>
<tr>
<td><%= post.title %></td>
<td><%= post.body %></td>
<td><%= post.author.name %></td>
<td><%= post.created_at %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
Now the links will be sorted. Happy searching and sorting!