Fernando Luizão

Desenvolvimento de software e nerdices em geral

Rails: Autocompletes à moda RESTful

with one comment

Muita gente tem reclamado que o padrão RESTful do Rails é ruim, que limita, dificulta, etc. Eu não concordo, acho que limitações nos forçam a pensar em soluções mais simples. Realmente, manter-se RESTful não é tão simples quanto sair criando um monte de actions para qualquer coisa, principalmente nos casos de uso de ajax. Uma das reclamações que eu ouvi foi sobre dificuldade em usar autocompletes, por isso nesse artigo vamos ver como resolver esse “problema” e fazer um auto complete RESTful de forma simples e elegante.

Vamos lá, criando o projeto para teste e um resource Pessoa

rails restful_autocomplete
cd restful_autocomplete
script/generate scaffold pessoa nome:string
rake db:migrate

Instalando o plugin auto_complete:

script/plugin install git://github.com/rails/auto_complete.git

É necessário ter o git instalado, caso vc não tenha, ou não esteja com vontade de instalar, baixe o plugin aqui e descompacte em vendor/plugins.

Esse plugin possui uma macro para gerar a action de resposta do auto complete, mas como estamos usando um controller RESTful, não vamos usá-lo dessa maneira. Em vez disso, vamos criar uma mini-API para lidar com o problema. A idéia central é que TODAS as requisições que necessitem recuperar uma coleção de pessoas usem como ÚNICO ponto de acesso a action index.

O plugin espera os registros formatados dentro de uma lista não ordenada, por exemplo:

<ul>
	<li>Item 1</li>
	<li>Item 2</li>
        ...
	<li>Item N</li>
</ul>

Com isso em mente, vamos criar um novo mime-type para que nosso controller se encarregue de identificar a requisição do auto complete e devolver o formato correto. Adicione a seguinte linha ao arquivo config/initializers/mime_types.rb:

Mime::Type.register_alias "text/html", :autocomplete

Estamos registrando o tipo customizado “autocomplete” como HTML. Lembre-se de reiniciar o servidor depois de alterar o arquivo.

Agora criaremos um controller qualquer que fará a requisição pelo auto complete:

script/generate controller testes new

Na view testes/new.html.erb, coloque o seguinte:

<%=
    text_field_with_auto_complete :bla, :ble, { :size => 25 }, {
      :url => formatted_pessoas_path(:autocomplete),
      :method => :get,
      :param_name => 'nome'
    }
%>

Passamos algumas opções ao helper text_field_with_auto_complete fornecido pelo plugin:

  • Na linha 3 indicamos a url (ou melhor, o RECURSO) à qual a requisição será ser feita e o mime-type que desejamos (o “autocomplete” que nós criamos). A url gerada será /pessoas.autocomplete
  • Na linha 4 estamos dizendo que queremos que a requisição seja feita pelo método GET (LEMBRE-SE: A action index só é acessivel por GET em um controller RESTful)
  • Finalmente na linha 5 especificamos com qual nome o conteúdo do text_field será enviado. O valor do parâmetro depois poderá ser acessado com params[:nome].

A action index do controller pessoas (nossa “API”), responsável pelo trabalho sujo, ficará assim:

def index
  conditions = ["nome LIKE ?", "%#{params[:nome]}%"] if params[:nome]
  @pessoas = Pessoa.all :conditions => conditions

  respond_to do |format|
    format.html # index.html.erb
    format.xml  { render :xml => @pessoas }
    format.autocomplete  { render :inline => "<%= auto_complete_result @pessoas, :nome %>" }
  end
end

A idéia básica de uma API, é que ela receba parâmetros, processe-os, e devolva um resultado. Nossa API é extremamente simples, se receber um parâmetro “nome”, faz a pesquisa pelos nomes que forem similares, senão retorna todos os registros. Podemos incrementar nossa API e adicionar várias outras coisas, como mais opções para pesquisa (pesquisa por idade, por CPF…), limite de registros a serem retornados, paginação, e o que mais for preciso. Essa é a maior vantagem do padrão RESTful, em vez de uma action, você ganha uma API :).

A linha 7 é que faz a mágica de responder ao auto complete. Ela devolve os resultados da pesquisa no formato que o auto complete espera, na forma de lista não ordenada, usando o helper auto_complete_result.

Inicie o servidor, e acesse a url http://localhost:3000/testes/new e teste o auto complete.

Pronto, temos um auto complete RESTful! =)

Lembre-se, o modelo RESTful veio para facilitar nossa vida, não para complicar. RESTful restringe visando simplificar o design de nossas aplicações e nos forçar a construir APIs que nós mesmos consumimos (e obviamente, também ser consumidas por terceiros). Limitações são impostas apenas por nós mesmos, por isso, pare de se limitar :).

NOTA 1: Não esqueça de incluir os javascripts necessários no seu layout, senão não vai funcionar:

<%= javascript_include_tag :defaults %>

NOTA 2: Os helpers de rotas formatados serão removidos nas próximas versões do Rails. Em vez de:

formatted_pessoas_path(:autocomplete)

Ficará:

pessoas_path(:format => :autocomplete)

Então atenção à versão do Rails que vc está usando. Mais detalhes aqui.

Advertisements

Written by fernandoluizao

January 24, 2009 at 1:53 pm

Posted in Rails

Tagged with , ,

One Response

Subscribe to comments with RSS.

  1. Muito bem explicado.. já tive dificuldades no passado para usar autocomplete, acabei criando uma div para fornecer os resultados..
    Favoritado!

    fabianosoriani

    April 2, 2009 at 6:05 pm


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: