Rails e Javascript: Escrevendo seu próprio javascript.

by Márcio Gasparotto on December 9, 2009

O integração padrão entre Ruby on Rails e Javascript sempre foi muito boa, as possibilidades com rjs, métodos que respondem javascript, json, etc. ajudam muito.

Mas o que vou falar hoje é sobre como escrever seu próprio javascript, sem depender dos helpers do rails. Na minha opinião, embora a integração existente ajude muito, quando queremos ir pouco mais fundo, ou em um projeto muito grande que exija mais do que simples chamadas ajax eu prefiro criar meu próprio javascript, isso pelo simples fato de que faço do jeito que eu quero, organizo minha biblioteca de arquivos js da forma que melhor se adapta ao projeto e tenho total controle sobre o que estou fazendo, não fico “preso” ao jeito de fazer “imposto” pelo rails.

Só um aparte neste ponto, NÃO estou dizendo que rjs é ruim pelo contrário ele ajuda muito em muitas coisas.

Bem, dito isso vamos por a mão na massa! Em primeiro lugar aviso que usarei o jquery ao inves do prototype, não vou entrar em detalhes de como configurar o jquery no rails pra isso você pode usar o jrails (eu uso).

O cenário que escolhi para esse post foi algo bem básico, só para exemplificar mesmo, imagine o seguinte: Um cadastro de produtos, esses produtos tem uma categoria e uma subcategoria, então quando eu escolher uma categoria em um select quero que o select de subcategorias seja carregado dinamicamente:

o meu controller eu adiciono o seguinte metodo:

    1 def ajax_load_sublinhas
    2   linha = params[:linha] || 0
    3   @sublinhas = Sublinha.sublinha_by_linha(linha).collect { |c| [c.description, c.codesublinha] }
    4   render :layout => false
    5 end

Ai na view do metodo:

    1 <li id="product_codesublinha_input" class="select optional">
    2 <label for="product_codesublinha">SubLinha</label>
    3 <% if @sublinhas.empty? %>
    4   nenhuma sublinha foi encontrada.
    5 <% else %>
    6 <%= select_tag 'product_codesublinha', options_for_select(@sublinhas),
    7                                        :name => "product[codesublinha]" %>
    8 <% end %>
    9 </li>

Por fim no meu formulário, na pagina de cadastro de produto:

    1 <% content_for :header do -%>
    2   <%= javascript_include_inputs %>
    3   <script type="text/javascript" charset="utf-8">
    4     $(document).ready(function() {
    5       $("#product_codelinha").change(function() {
    6         show_overlayer();
    7
    8         $.get('http://localhost:3000/products/ajax_load_sublinhas', { linha: $('#product_codelinha').val()}, function(sublinhas){
    9           $('#sublinhas').empty();
   10           $('#sublinhas').append(sublinhas);
   11           hide_overlayer();
   12         });
   13
   14         return false;
   15      });
   16   });
   17
   18 function show_overlayer(){
   19   $("#overlayer").css("display","block");
   20   $("body").css("overflow","hidden");
   21 }
   22
   23 function hide_overlayer(){
   24   $("#overlayer").css("display","none");
   25   $("body").css("overflow","auto");
   26 }
   27 </script>
   28 <% end -%>
   29 <div id="form">
   30 <% semantic_form_for @product do |form| %>
   31
   32   <% form.inputs do %>
   33     <%= form.input :code_product, :label => true, :input_html => {:size => 5, :class => "small"} %>
   34     <%= form.input :name, :label => true %>
   35     <%= form.input :codelinha, :as => :select, :collection => @linhas, :label => 'Linha' %>
   36     <div id="sublinhas">
   37     <% if @product.new_record? %>
   38     <% else %>
   39     <%= form.input :codesublinha, :as => :select, :collection => @sublinhas, :label => 'SubLinha' %>
   40     <% end %>
   41     </div>
   42     <%= form.input :stock, :label => true, :input_html => { :size => 3, :class => "small" } %>
   43     <%= form.input :cost_price, :label => true, :mask => :decimal,
   44                                 :input_html => {:size => 5, :class => "small"} %>
   45     <%= form.input :retail_price, :label => true, :mask => :decimal,
   46                                 :input_html => {:size => 5, :class => "small"} %>
   47     <%= form.input :description, :label => true %>
   48     <%= form.buttons :commit %>
   49   <% end %>
   50
   51 <% end %>
   52 </div>

Vejam que para o exemplo eu estou usando o formtastic, por isso o formulário um pouco diferente do convencional.

Lembre sempre de setar o método no routes.rb também

map.resources :products, :collection => { :ajax_load_sublinhas => :get }

Vejam que temos muita liberdade para fazer a coisa do nosso jeito, esse foi só um exemplo bem simples de selects dinâmicos, mas o leque de coisas que podemos fazer é o quanto a nossa imaginação permitir.

Qualquer dúvida é só comentar.

This is it!

2 comments

Boa Noite Marcio, tudo bem ??

Estou comecando a aprender Rails, e esse exemplo que voce deu é algo que estou tentando fazer.

Vi seu exemplo mas nao entendi muito bem. Sera que voce nao tem o codigo completo desse projetinho para me enviar para que eu veja e estude melhor cada parte.
Meu email é fabio.rails[ at ]gmail.com

Grato

by Fabio on February 11, 2010 at 6:08 pm. #

Oi Fábio, tudo bem!

Então, eu escrevi esse post baseado em algo que precisei fazer para um cliente, esse código foi só para exemplificar mesmo, não tenho o código completo do “projetinho”.

Mas qualquer dúvida posta ai.

Tem também o grupo rails-br no google que pode te ajudar.

Abração.

by Márcio Gasparotto on February 12, 2010 at 3:44 am. #

Leave your comment

Required.

Required. Not published.

If you have one.