没有Rails的内置助手使用AJAX的最佳实践?

时间:2009-04-29 18:30:48

标签: jquery ruby-on-rails ajax unobtrusive-javascript

在我的博客应用程序中,一些帖子显示为摘录 - 即,用户看到第一个(比如说)500个字符,并且可以单击链接以查看整个帖子。以下是相关部分:

<% 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 => "&hellip;<h1><a class='more' href=\"#{href}\">Click here for more!</a></h1>") %>
  <% else %>
    <%= post.body %>
  <% end %>
</div>

但是,而不是“点击此处了解更多信息!”将用户带到一个单独的页面,我希望它能够填充内联的其余部分。目前,我已经通过将上面的代码段放在以下div中来实现这一点:

<div class="post" id="post_<%= post.id %>">
  <%= render :partial => 'post_content', :locals => { :post => post, :length => 500 } %>
</div>

然后我在我的application.js中使用这个div的id来做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;
  });

});

这显然令人作呕 - 我不希望我的javascript依赖于链接的href中帖子id的位置,但我不知道javascript知道它获取的帖子的任何其他方式因此应该在哪个div中插入内容。

实现这一目标的最佳方法是什么?我应该回到使用rails的AJAX助手吗?

3 个答案:

答案 0 :(得分:7)

霍拉斯,你是对的。你根本不需要Rails助手。为了实现不引人注目的JavaScript Nirvana,你最好避免它们(对不起Marc!)

Unobstrusive JS意味着尽可能避免使用嵌入式JS。实际上,尽量保持松散耦合,但不能完全脱钩。在您给我们的示例中,这很简单,因为我们有一个来自HREF的URL可以使用。您的JS不需要“知道”有关如何请求的任何内容。

以下是如何从HREF盲目发送链接,并让Rails响应ajax响应(即没有布局)。

<强> SOLUTION:

<!------- 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").click(function() { $containing_div = $(e).parents('div.body'); var url = $(this).attr('href'); $.ajax({ beforeSend : function(request) { request.setRequestHeader("Accept", "text/javascript"); }, /* Included so Rails responds via "format.js" */ success : function(response) { $(containing_div).empty.append(response); }, type : 'get', url : url }); return false; });

});

########### 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

这也假设您有RESTful路由或类似于handle / post /:id

我们已经完成了!我相信对我们所有人来说都有一些东西。 :d

答案 1 :(得分:1)

在这种情况下,我认为您根本不应该进行AJAX调用。你已经在post.body中拥有了原始帖子的全部内容(你没有从db中获取500个字符)而不是使用JQuery进行ajax调用,使用它来隐藏超过500个字符的内容然后当用户点击“更多”链接,它会显示div的其余部分。您可以在客户端完全执行此操作并自行保存ajax。

在你的部分:

<div class="body">
  <%= post.body %>
</div>

你的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;
}

答案 2 :(得分:0)

在我看来,对于这类问题,你应该使用rails'帮助器。

HTML会像:

My post bla bla bla <span id="more_of<%=post.id%>">more</span>

链接越多:

<%= link_to_remote( "more",:update => "more_of_#{your_post.id}",:url =>{:controller => "myposts", :action=>"show_more", :id => your_post.id}, %>

控制器可以执行以下操作:

post = Post.find_by_id(params[:id])
render :text => post.content.slice(100..post.content.size) 

另一种可能同样好的方法是加载所有内容然后隐藏它:

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>

(关于div标签的onclick可能会在IE中断,但这是为了给你一个想法)

对我而言,这是最好的方法,除非你有充分的理由避免铁路助手。

希望有所帮助