Rails 4: como parciais e AJAX, muito fácil

Considere o seguinte cenário básico …

Uma visualização com duas colunas:

  • um com links de instâncias de modelo de categoria

  • o outro vazio, mas ansioso para mostrar todas as instâncias de Item pertencentes a cada categoria.

E você quer mostrar tudo isso sem recarregar a página. Eu nunca tinha jogado muito com parciais em Rails, mas eles são realmente muito convenientes.

Então, eu tenho meu método de índice

#items_controller.rb
def index
@items = Item.all
@categories = Category.all
end

Por uma questão de brevidade, simplificarei as visualizações. Dessa forma, você também pode entender a ideia e aplicá-la às suas próprias visões.

A visualização do índice contém duas chamadas de renderização

<!-- items/index.html.erb -->
<div class="grid">
<%= render 'sidebar_menu' %>

<%= render partial: 'item_grid', locals: { items: @items} %>
</div>

Os links de categoria na sidebar_menuparcial são mais ou menos como o seguinte:

<%= link_to cat.name, fetch_items_path(:cat_id => cat.id), :remote => true %>

fetch_items_path é a rota que leva ao nosso método javascript personalizado, que será descrito a seguir.

#config/routes.rb
...
get
"/fetch_items" => 'items#from_category', as: 'fetch_items'

Para mais informações sobre como construir rotas personalizadas, verifique a incrível documentação do Rails.

A é a parte mais importante aqui, ela permite todo o negócio Ajax em primeiro lugar.:remote => true

A item_gridparcial se parece com:

<div>
<div id="items_grid" >
<%= render partial: 'items_list', locals: {items: items} %>
</div>
</div>

O subparcial items_listapenas renderiza uma lista de caixas div para mostrar nossas instâncias de Item.

<% items.each do |item| %>
<div class="item_box">
...

</div>
<% end %>

Agora precisamos do método que fará a mágica do AJAX. Para simplificar, você poderia ter algo assim:

#items_controller.rb
def from_category
@selected = Item.where(:category_id => params[:cat_id])
respond_to
do |format|
format
.js
end
end

Observe o tipo de formato, não há visão html porque não precisamos dela. Estamos passando por JS.
Portanto, precisamos criar um arquivo javascript, que irá preencher novamente o div na segunda coluna.

//views/items/from_category.js.erb
$
("#items_grid").html("<%= escape_javascript(render partial: 'items_list', locals: { items: @selected } ) %>");

Vamos examinar essa linha com cuidado.
Estou renderizando o mesmo parcial que estava renderizando em items # index, e a variável local para o partial agora é a matriz de instâncias de Item que correspondem a uma determinada categoria. A diferença é que estou fazendo isso por meio de AJAX, portanto, não há necessidade de recarregar a página inteira.