Ruby Gem: Escopo de busca fácil no ActiveRecord

Escrevi a algum tempo um post mostrando como usar campos FULL TEXT do MySQL para ter uma sistema de busca simples mas eficiente em suas aplicações Rails. Para quem não precisa de uma busca mais sofisticada, o plugin acts_as_fulltextable quebra o galho.

Porém, recentemente me deparei com um situação onde precisava de algo ainda mais simples. Para um sistema de administração de conteúdo, a busca devia pesquisar apenas em um Model, e em apenas alguns campos. Portanto criar uma tabela extra no banco de dados, como o acts_as_fulltextable faz, seria um pouco dispendioso.

Uma solução simples seria usar o método Model.find_by_name por exemplo, para buscar um registro pelo campo 'name', mas isso traria apenas um registro e sem a possibilidade de buscar por mais de um campo com uma única execução. Outra solução seria a criação de named_scopes, mas seria um tanto trabalhoso filtrar por vários atributos e ainda tratar a entrada de dados. Foi então que encontrei a gem scoped_search. Quando instalada, ela adiciona um escopo para buscas em models do Active Record chamada search_for, a qual usa cláusulas LIKE da linguagem SQL para efetuar filtros, diretamente no banco de dados.

Instalação:

Adicione ao environment.rb de sua aplicação:

config.gem 'scoped_search',

Depois, execute o comando:

$ rake gems:install

Utilização:

Basta adicionar uma linha no Model desejado, indicando os campos que serão usados na busca:

# user.rb
class User < ActiveRecord::Base
  searchable_on :login, :name
end

Depois da alteração, a classe passa a contar com o escopo search_for, que pode ser usado em cascata com outros named_scopes. No exemplo abaixo de uma action "search" do controller de usuários, integra-se a busca com a paginação provida pelo will_paginate:

# users_controller.rb
def search
  @users = User.search_for(params[:q]).paginate(:page => params[:page])
  respond_to do |format|
    format.html
    format.xml{ render :xml => @users }
  end
end

Bem tranquilo. Para incrementar um pouco, podemos ainda adicionar campos de associações na busca. Supondo que o usuário tenha um perfil (profile), podemos adicionar o campo description pertencente ao perfil na busca, da seguinte maneira:

class User 
  has_one :profile, :dependent => :destroy
  searchable_on :login, :name, :profile_description
end

No MySQL, pode-se ainda utilizar índices FULLTEXT nos campos mais requisitados, para aumentar a performance das buscas.

Fonte: Easy search with ActiveRecord

Published on in Blog