Melhores práticas para usar AJAX sem os ajudantes integrados do Rails?
-
03-07-2019 - |
Pergunta
No meu aplicativo de blog, algumas postagens aparecem como trechos - ou seja, o usuário vê os primeiros (digamos) 500 caracteres e pode clicar em um link para visualizar a postagem inteira.Aqui está a parcial relevante:
<% href = url_for post_path(:id => post) %>
<h1 class="title"><%= post.title %></h1>
<h2 class="published_on"><%= post.author %> wrote this <%= time_ago_in_words(post.published_on)%> ago</h2>
<div class="body">
<% if defined?(length) %>
<%= truncate_html(post.body, :length => length, :omission => "…<h1><a class='more' href=\"#{href}\">Click here for more!</a></h1>") %>
<% else %>
<%= post.body %>
<% end %>
</div>
No entanto, em vez de "Clique aqui para mais!" Levando o usuário a uma página separada, gostaria que ela preencha o restante da postagem em linha.Atualmente, estou implementando isso colocando o trecho acima na seguinte div:
<div class="post" id="post_<%= post.id %>">
<%= render :partial => 'post_content', :locals => { :post => post, :length => 500 } %>
</div>
Eu então uso o id dessa div no meu application.js para fazer o AJAX:
$(document).ready(function() {
$("a.more").click(function() {
var url = $(this).attr('href');
var id = url.split("/")[2]
$.get(url, null, function(data) {
$("#post_" + id).html(data);
});
return false;
});
});
Obviamente, isso é nojento - não quero que meu javascript dependa da localização do ID da postagem no href do link, mas não conheço outra maneira de o javascript saber qual postagem está recebendo e, portanto, em qual div o conteúdo deve ser inserido.
Qual é a melhor maneira de conseguir isso?Devo voltar a usar os auxiliares AJAX do Rails?
Solução
Horácio, você está correto.Você não precisa dos ajudantes do Rails.Para alcançar o JavaScript Nirvana discreto, você fará bem em evitá-los (desculpe, Marc!)
JS discreto significa evitar JS incorporado sempre que possível.Na verdade, tente manter as coisas fracamente acopladas, mas não totalmente dissociadas.No exemplo que você nos deu é fácil, pois temos uma URL do HREF para trabalhar.Seu JS não precisa “saber” nada sobre como solicitar.
Aqui está como enviar cegamente o link do HREF e fazer com que o Rails responda com uma resposta ajax (ou seja,sem layout).
SOLUÇÃO:
<!------- Your HTML ------>
<h1 class="title">Schwein Flu Strikes Again</h1>
<h2 class="published_on">B.Obama wrote this 2 seconds ago</h2>
<div class="body">
SUMMARY SUMMARY
<h1><a class='more' href="/post/1234">Click here for more!</a></h1>
</div>
/********* Your JavaScript ***********/ $(document).ready(function() {
$ ("a.more"). Clique (function () {$ contening_div = $ (e) .parents ('div.body');var url = $(this).attr('href');$ .ajax ({beforesend:function(solicitação) { request.setRequestHeader("Aceitar", "texto/javascript");}, / * Incluído SO Rails responde via "format.js" * / success:function(resposta) { $(containing_div).empty.append(response);}, tipo :'Get', URL:url});retorna falso;});
});
########### Your Controller ###########
def show
@article = Post.find(param[:id])
respond_to do |format|
format.html { render :action => "show" and return }
format.js { render :partial => "post_content", :layout => false and return }
end
end
Isso também pressupõe que você tenha rotas RESTful ou similares para lidar com /post/:id
E terminamos!Acredito que há algo nisso para todos nós.:D
Outras dicas
Neste caso, eu não acho que você deve ter a chamada AJAX em tudo. Você já tem todo o conteúdo do post original em post.body (você não buscar apenas os 500 caracteres do db) Em vez de usar JQuery para fazer uma chamada ajax, usá-lo para ocultar o conteúdo passado 500 caracteres e, em seguida, quando o usuário clica no link 'mais' que mostra o resto do div. Você pode fazer isso inteiramente no lado do cliente e salve-se o ajax.
Em sua parcial:
<div class="body">
<%= post.body %>
</div>
Seu JQuery:
var fullText = $('div.body').html();
$('div.body').html(fullText.slice(0,499) + '<a class="more" href=\"#\">Click here for more!</a>');
$('a.more').live('click', function(event) {
this.parent().html(fullText);
return false;
}
Na minha opinião para este tipo de problemas você deve usar ajudantes trilhos.
HTML iria como:
My post bla bla bla <span id="more_of<%=post.id%>">more</span>
O mais ligação seria:
<%= link_to_remote( "more",:update => "more_of_#{your_post.id}",:url =>{:controller => "myposts", :action=>"show_more", :id => your_post.id}, %>
E o controlador faria algo como:
post = Post.find_by_id(params[:id])
render :text => post.content.slice(100..post.content.size)
A outra forma que poderia ser tão bom é carregar tudo e depois escondê-lo:
bla bla bla this is my post blah <div style="display:none" onclick="this.style.display='block';">and this is the rest of the article</div>
(o onclick em uma tag div pode quebrar no IE, mas isso é dar-lhe a idéia)
Para mim, isso seria a melhor maneira de ir a menos que você tenha uma boa razão de evitar ajudantes trilhos.
Espero que ajude