Skip to content

Rodrigo Urubatan – About Code

Helping ruby developers to use the best tools for each job so they can solve hard problems, with less bugs and have more free time.

Menu
  • Home
  • My last presentations
  • About
  • Privacy Policy
Menu

Have you ever needed to provide an “advanced search” to your users?

Posted on 2018-09-05 by Rodrigo Urubatan

Working on a project some time ago, and my boss wanted to have an advanced search, where the users could write the search, adding fields, values, like you can do with google, but tailored for our application.

In google you can do things like searching for all posts from sobrecodigo.com that have Ruby in the title searching for “allintitle: ruby site:sobrecodigo.com”

First try I implemented a complex field search algorithm, breaking the search string, accounting for apostrophes, having a field/content separator, it worked but it is a lot of work and very error prone, the second time I had to do something similar, but a little more powerful for another project, a coworker introduced me to “search_cop“, a really cool ruby gem that made my life a lot easier.

So I thought this kind of request could be more common and maybe not everyone know about this gem that helped me a lot 😀

To use it, let’s create a simple Rails project and some models like this:

rails new advancedsearch_sample
cd advancedsearch_sample
rails g model reporter full_name:string email:string
rails g model category name:string
rails g model status name:string
rails g model story reporter:belongs_to headline:string content:text status:belongs_to
rails g model story_category story:belongs_to category:belongs_to

Now we can add the ‘search_cop’ gem to our Gemfile, run bundler and db:migrate, then jump straight to editing the story model to add some search capabilities like this:

class Story < ApplicationRecord
  include SearchCop
  belongs_to :reporter
  belongs_to :status
  has_many :story_categories
  has_many :categories, through: :story_categories
 
  search_scope :search do
    attributes :headline, :content
    attributes reporter: 'reporters.full_name'
    attributes category: 'categories.name'
    scope do
      joins(:categories, :reporter, :status)
        .where(statuses: {name: 'Published'})
        .order('id desc')
    end
  end
end

I’ll explain everything, but with this, you can now search for stories, like this:

Story.search("headline:ruby content:'pro tip' reporter:rodrigo category:'full article'")

or better yet, like in my case, let your users build the query, using a really cool text field with syntax highlight and code completion 😛

But back to the subject, the requirement was to let users write advances queries, and this gem allowed me to do so in a really easy way.

For example, the query above will search for:

  • Published stories
  • Having ‘ruby’ in the headline 
  • Having ‘pro tip’ in the content
  • Reported by someone with rodrigo in the name
  • in a category that has ‘full article’ in the name

In the search string, you can also pass AND, OR, negate a condition with a simple ‘-‘ sign, for sates and numbers you can use < and > comparisons.

You can also make the ‘reporter’ field search both in the reporter full_name and email, just by passing an array with both fields in the attributes configuration, and specify joins and wheres in the scope section.

Of course you can have multiple search scopes for one model, and you can also chain the search scope with any active record method you need.

And of course it is not perfect, all the string comparisons are done with “like ‘%…%'”, so the performance will not be great.

If you are using MySQL or PostgreSQL full text capabilities you can configure search_cop to use it instead of LIKE for that fields.

If you have the specific field value, you can use ‘=’ instead of ‘:’, or quoting search_cop documentation, you can use any of these operators: AND/and, OR/or, :, =, !=, <, <=, >, >=, NOT/not/-, ()

And whenever you do not specify AND or OR “AND” is assumed.

This gem has helped me a lot by now, I just wanted to share this, because it can help others.

Did you already know this gem? are you using other gems that do a similar job?

Related

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent posts

  • Why Embrace Nesting in Ruby Modules?
  • An easy way to have a local “Github Copilot” for free
  • SPA without touching Javascript – The magic of Ruby on rails and Hotwire
  • I see Dead Jobs everywhere (sidekiq DeadSet)
  • Quick tips that help: rails notes

Arquives

  • May 2024
  • April 2024
  • February 2023
  • January 2023
  • December 2022
  • June 2021
  • March 2020
  • January 2020
  • July 2019
  • June 2019
  • May 2019
  • October 2018
  • September 2018
  • August 2018
  • July 2018
  • June 2018
  • May 2018
  • February 2018
  • January 2018
  • November 2017
  • August 2015
  • August 2014
  • July 2014
  • August 2007

Categories

  • AI
  • articles
  • cfp
  • firebase
  • gems
  • git
  • opinion
  • presentations
  • projects
  • rails6
  • ruby
  • Sem categoria
  • server-api
  • tutorials
  • Uncategorized
© 2025 Rodrigo Urubatan – About Code | Powered by Minimalist Blog WordPress Theme