Ajax:成功不在rails app中工作

时间:2015-01-18 02:46:16

标签: ruby-on-rails ruby ajax json turbolinks

在rails 4 app中,我使用link_to通过json在帖子上发送upvote。

以下是我在帖子控制器中的内容:

def upvote
  @post = Post.find(params[:id])
  @post.liked_by current_user

    respond_to do |format|
    format.html {redirect_to :back }
    format.json { render json: { count: @post.get_upvotes.size } }
  end
end

以下是我的观点

<%= link_to like_post_path(post), method: :put, class: 'vote', remote: true, data: { type: :json } do %>
    <%= image_tag('vote.png') %>
    <%= content_tag :span, post.get_upvotes.size %>
    <% end %>


    <script>

    $(document)
        .on('ajax:send', '.vote', function () { $(this).addClass('loading'); })
        .on('ajax:complete', '.vote', function () { $(this).removeClass('loading'); })
        .on('ajax:error', '.vote', function(e, xhr, status, error) { console.log(status); console.log(error); })
        .on('ajax:success', '.vote', function (e, data, status, xhr) {
        $(this).find("span").html(data.count);
        $(this).find("img").attr("src", '<%= asset_path 'voted.png' %>'); 
        });


    </script>

当我点击链接时,投票作为JSON请求进行,我在日志中看到了这一点:

Processing by PostsController#upvote as JSON

但由于某种原因,我的剪辑javascript无效。计数器或图标都不会更新。 我该如何解决这个问题?这与turbolinks有关吗,它与我放置javascript的位置有关吗?

2 个答案:

答案 0 :(得分:1)

jQuery是默认的rails javascript库。默认的rails javascript库曾经是prototype,因此旧的教程/文档使用它。这就是ajax在jQuery中的样子:

应用程序/控制器/ static_pages_controller.rb:

class StaticPagesController < ApplicationController

  def show_link
  end

  def upvote
    respond_to do |format|
      format.json {render json: {"count" => "10"} }
    end
  end

end

应用程序/视图/ static_pages / show_link.html:

<div>Here is an ajax link:</div>

<%= link_to(
    "Click me", 
    '/static_pages/upvote', 
    'remote' => true,  #Submit request with ajax, and put text/javascript on front of Accept header
    data: { type: :json })  #Put application/json on front of Accept header
%>


<div>Upvotes:</div>
<div id="upvotes">3</div>

<script>
$(document).ready( function() {

  $(this).ajaxSuccess( function(event, jqXHR, ajaxInfo, data) {

    //var js_obj = JSON.parse(jqXHR.responseText);
    //$('#upvotes').html(js_obj["count"]);

    //Apparently, the fourth argument to the handler, data,
    //already contains the js_obj created from parsing the  
    //json string contained in the response. 

    $('#upvotes').html(data["count"]);
  });

}); 
</script>

配置/ routes.rb中:

Test1::Application.routes.draw do

  get 'static_pages/show_link'
  get 'static_pages/upvote'
  ...
end

要在浏览器中输入网址:

http://localhost:3000/static_pages/show_link

请在此处查看jquery文档:

http://api.jquery.com/ajaxSuccess/

对评论的回应:

您还可以在控制器中执行以下操作:

  def upvote

    @upvotes = 2  #Set an @variable to the number of upvotes

    respond_to do |format|
      format.js {}  #By default renders app/views/static_pages/upvote.js.erb
    end

  end

然后:

应用程序/视图/ static_pages / upvote.js.erb:

$('#upvotes').html(<%= @upvotes %>)

答案 1 :(得分:1)

在Rails中,您可以通过JavaScript响应执行类似的任务。添加与respond_to类似的format.js format.html,然后看一下upvote.js.erb的视图:

(function() {    

var postId = "#post-<%= @post.id %>";

$(postId).find(".vote").find("span").text("<%= @post.get_upvotes.size %>");
$(postId).find(".vote").find("img").attr("src", "<%= asset_path "voted.png" %>");

})();

我将您的通话更改为.html.text,因为您实际上未在该元素内设置任何HTML,因此没有理由致电.html

这篇文章还假设有一些机制来识别投票链接所属的帖子(在示例中,父帖子元素的ID为&#34; post - #&#34;其中#是的是邮件对象)。

修改

如果我正在处理这个项目,我会做出两个改变。首先,我将voted.png路径作为数据属性附加到.vote元素。 data-voted-image-src="<%= asset_path "voted.png" %>"。接下来,我绝不会在回报中传递一个数字,因为没有理由这样做。点击投票后,您可以通过假设请求成功来处理前端的所有内容。这节省了所有这些潜在的肮脏。虽然我意识到从现有的内容改为添加数据属性并不是一个巨大的飞跃,但我发现它比在JavaScript中更具语义性。

投票链接上的点击操作将变为:

// Assume all posts have a class 'post'
// I'm also using 'one' because once they vote they don't need to anymore
$(".post").find(".vote").one("click", function(e) {
  var count = parseInt($(this).find("span").text()),
      votedSrc = $(this).data("voted-image-src");
  $(this).find("img").attr("src", votedSrc);
  $(this).find("span").text(count + 1);
});

现在无需服务器响应,您可以将JSON响应更改为{success: true}或简单的内容。