【问题标题】:Ruby on Rails Ajax call runs controller code, returns success, but not rendering viewRuby on Rails Ajax 调用运行控制器代码,返回成功,但不呈现视图
【发布时间】:2017-04-04 19:01:43
【问题描述】:

我的页面上有一个有效的搜索机制;带有文本字段和带有“搜索”标签的提交按钮的表单。

我的页面上还有一个基于 raphael.js 的动画项目,上面有我想要执行搜索的可点击项目。

点击时,我向控制器发送数据,这些数据旨在作为从 raphael 对象中提取的搜索词。

正在传递数据,控制器代码运行,但相应的视图无法呈现,因此点击对用户来说似乎什么都不做。

所以在点击时,我会像这样进行 Ajax 调用:

文件 searchthing.js

            // Add a search function
            circle.click(function (e) {
                var csrch = this.data('label');
                // alert('clicked ' + csrch);
                e.preventDefault();
                $.ajax({
                    type: "GET",
                    url: "/bubbleBar",
                    data: $.param({ srchterm: csrch} ),
                    success: function(){
                        // window.location.replace("/pictures");
                    },
                    error: function(XMLHttpRequest, textStatus, errorThrown) {
                        alert("--- error: " + errorThrown);
                    }
                });
            });

我的控制器中的“bubbleBar”动作成功触发,传输搜索词,并重定向到我的工作索引动作,它处理搜索:

文件 myController.rb:

def bubbleBarSearch
    redirect_to pictures_path(:srchterm => params[:srchterm])
end

def index
    # Initialize the pictures array
    #
    @pictures = Picture.first
    if params[:srchterm].present?

        # If the search button was hit, search pictures for the terms
        @pictures = []
        results = Picture.search(params[:srchterm], page: params[:page])
        results.each do |x|
            @pictures << x
        end

        # Also search keywords for the search terms
        #
        keywords = Keyword.search(params[:srchterm], page: params[:page])

        # Retrieve images based on keywords
        #
        keywords.each do |kw|
            pics = Picture.where(:id => kw.picture_id)
            pics.each do |pic|
                # Only add to results if unique
                #
                if !@pictures.include? pic
                    @pictures << pic
                end
            end
        end
        respond_to do |format|
            format.html {
                puts '---------------- ding -----------------'
                # Redirect_to pictures_path
            }
            format.js {alert('dong');}
        end
    else
        @pictures = Picture.all.order("RANDOM()")
    end
end

我遇到的问题是 Ajax 返回成功,但“索引”操作的相应视图没有呈现。

如果我取消注释 'window.location.replace("/pictures");'我的 JavaScript 代码中的行,我可以强制渲染成功,但我丢失了控制器代码为我获得的搜索结果。如果我取消注释控制器中的“redirect_to pictures_path”行,我当然会得到一个无限循环错误出去。

到目前为止我所做的研究告诉我应该在控制器中捕捉响应。

我之前没有使用过 respond_to,并且似乎 format.html 被 Ajax 调用命中,但是当我使用页面上已经设置的搜索字段/按钮机制手动进行搜索时也会触发。我不清楚为什么我的 Ajax 调用以 HTML 而不是 JavaScript 的形式出现。

这意味着如果我在控制器中手动处理视图的呈现,我不会发现当搜索没有通过已经工作的机制并且冒着呈现页面两次或以其他方式引入的风险时我的网站出现故障。

我不知道如何让我的 click/Ajax 调用在控制器操作发生后成功地从 click 函数呈现所需的视图。我在这里想念什么?实现这一目标的理想方法是什么,并且不会丢失我需要成功渲染的控制器数据?

Ruby on Rails 的输出表明服务器认为它正在呈现正确的 Haml 视图文件,但是我在文件底部放置了一个 JavaScript 标记以将输出记录到控制台,单击后控制台为空。如果我通过站点导航到同一个视图,该语句将输出到控制台。

我已经修改了我的 Ajax 成功回调以具有一个参数,并且在检查后该变量包含视图的 HTML 代码。那么Ruby on Rails 是否将输出定向到Ajax 而不是浏览器?然后如何从 Ajax 成功回调中呈现该输出?

对控制器的成功调用包含我的 Ajax 调用中没有的 utf8 参数。这是一个因素吗?

【问题讨论】:

    标签: ruby-on-rails ajax redirect render


    【解决方案1】:

    重定向通过向浏览器返回一个状态码redirected来工作,这会导致浏览器对响应头中返回的url进行后续请求。因此,问题在于您的 bubbleBarSearch 操作返回状态为重定向到您的 ajax 调用。它实际上并没有在您的索引操作中运行代码。为什么不为您的索引操作创建一个路由并直接调用它呢?

    编辑 - 那是错误的,我明白你现在在问什么。要在回复中回答您的问题:

    啊,我明白了,看来你想按照 AlexeyKuznetsov 的建议去做。

    你需要if request.xhr,而不是respond_to do |format|。当您发出 ajax (xhr) 请求时,request.xhr 条件将为真,否则 rails 知道它是标准请求。我认为您的问题是您没有正确响应,这将呈现并返回它的视图呈现的任何 html,并将其返回给您的 ajax 请求。你可以告诉 rails 对不同类型的请求进行不同的渲染。要使用 javascript sn-p 响应,您可以使用 render js:http://guides.rubyonrails.org/layouts_and_rendering.html 搜索 Rendering Vanilla JavaScript),如

    if request.xhr
      render js: "alert('dong')"  # this is an ajax request
    else
      puts '-------- ding ---------` # this is not
    

    或者您可以渲染 json render json:,这将返回一个 json 响应。

    if request.xhr
      render json: {message: "ding"}
    else
      puts '-------- ding ---------` # this is not
    

    然后在你的axax成功函数中:

    success: function(data){
      console.log(data) // will have message: ding
      // window.location.replace("/pictures");
    },
    

    【讨论】:

    • 我使用过 byebug 并在单击后逐步执行索引操作控制器代码。它正在单击操作上运行,并且 ajax 正在返回成功,并通过警报进行验证。遵循您的建议的结果是相同的。即索引控制器动作执行完毕,ajax调用返回成功,新视图渲染失败。我添加了单独的目标,希望重定向会导致浏览器更改视图,而 ajax 直接调用索引操作没有。 index 操作在我添加此功能之前存在,并在其他情况下呈现视图。
    • 感谢您的更新,泰勒。现在我明白了 AlexeyKuznetsov 的建议。然而,我想要的来自 ajax 的响应不是消息,而是将适当的视图呈现给浏览器,最好是从服务器端。如果我省略了respond_to 和xhr 测试,则渲染页面的HTML 将发送到成功回调,如果我捕获了ajax 案例并渲染了一条消息,则不会在任何地方捕获视图HTML。有没有办法通过 ajax 调用将渲染视图从服务器端发送到浏览器?还是让成功回调在浏览器中呈现页面是公认的做法?
    • 我会说接受的做法是 1) 只需向您想要访问的新路由发出请求,而不是使用 ajax,或者 2) 通过 ajax 发出请求并返回一个 json 响应您的 javascript 可以分开并相应地更新 dom(操作页面上的 html 而不是本质上热交换 html)。您描述的功能接近于单页应用程序codeschool.com/beginners-guide-to-web-development/…。构建像 react 这样的前端框架可以更轻松地开发这种功能。
    【解决方案2】:

    format.js 这不是你的情况。我认为你应该走这条路:

    if request.xhr?
      # render data on ajax request 
    else
      # render view
    end
    

    【讨论】:

    • 感谢您的回复,但我需要更多信息来了解您提出的解决方案。这个逻辑放在哪里?我总是想在ajax动作触发控制器代码后渲染视图;为什么我需要这个逻辑?
    【解决方案3】:

    我有一个可行的解决方案来实现我的目标。它会在 chrome 中产生以下控制台警告:

    Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
    

    但是,它会向我的浏览器呈现适当的结果。如果有更合适的方法可以做到这一点,我很乐意学习。

    我发现要重定向到的呈现页面的整个 HTML - 包括 application.html.haml 中的站点页眉和页脚 - 正在返回给 Ajax 成功回调,并且不会被 rails 识别为 HTML。所以我现在用返回的数据替换整个页面正文的 HTML。这是通过三行代码完成的:

                        $.ajax({
                        type: "GET",
                        url: "/bubbleBar,
                        data: $.param({ srchterm: csrch} ),
                 >      dataType: "html",
                 >      success: function(response, status, request){
                 >          $('body').html(response);
                        )};
    

    我仍然不确定这 - 被“渲染”到成功回调的页面 - 是否正常和预期。此外,如果我的解决方案是将浏览器更改为所需页面的理想方法,或者如果我可以做一些事情来让这个页面在回调之外呈现给浏览器。可能不是,因为这是一个异步请求。

    我可以想象,如果用户在等待搜索完成时正在执行其他任务,那么部署时这可能会导致我的网站出现问题,但我目前没有更好的解决方案。我将考虑重新调整网站布局以防止出现此类问题。

    我还从控制器中删除了 respond_to 块,因为我无法确定任何方法让它仅在我需要它时执行我需要的操作。有可能现在我知道了 dataType: ajax 属性,我可以证明只有这个请求可以 ping,但是我无法确定在该语句的任何情况下适当的响应是什么,我只得到了我所有的尝试都出现 ajax 错误。

    感谢大家的建议,他们帮助我做到了最好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多