Rails 操作以状态 200 运行,但未访问模板且未触发 jQuery

Posted

技术标签:

【中文标题】Rails 操作以状态 200 运行,但未访问模板且未触发 jQuery【英文标题】:Rails action runs with status 200 but template not accessed and jQuery not fired 【发布时间】:2016-06-02 11:04:25 【问题描述】:

在下面的代码中,"$('#movesindexrowstable').DataTable(..." 永远不会触发。但是,"$('#movesindexlotstable').DataTable(..." 可以完美运行。

有趣的是,控制器“移动”操作“indexrows”呈现状态为 200,但模板并未执行,因为其中的断点不会触发。当然,如果没有执行模板,则不会处理 ID moveindexrowstable,这解释了为什么 jQuery 代码不会触发。

渲染代码 MovesIndexlotsDatatable 和 MovesIndexrowsDatatable 返回有效的 JSON。当然,即使没有,那也不应该影响渲染对模板的使用吗?

考虑到可能涉及 turbolinks,我将第一行更改为使用 page:change 而不是常见的 "$(document).ready(function () " 以符合其要求。这没有帮助,也没有确实添加了 data-no-turbolinks。

我通过 jquery-datatables-rails 使用 DataTables 和 AJAX 在表中显示 JSON 数据。但是,DataTables 永远不会获得控制权,因为选择器永远不会被识别并且函数不会触发。

这让我很困惑,如果能提供任何帮助,我将不胜感激。谢谢。

编辑:如果不是解决方案,我相信下面的图片可以隔离问题。 Moves#Indexlots 的初始 GET 呈现模板,随后的 POST 提供数据并且不呈现模板。到目前为止,我的编码仅包括 Moves#Indexrows 数据的 POST。看来我需要说服 POST 来呈现模板,或者找到另一种方法,例如通过 GET?如果是这样,我想就如何做到这一点提出建议。谢谢。

编辑:看起来像/答案? Render an html partial inside a JSON request

编辑: 在 JQ 中,我将 "$.post('/moves_indexrows.json'" 更改为 "$.post('/moves_indexrows.html'。这导致 POST 呈现预期的页面。网络跟踪显示页面大小为 15.6KB。Rails 跟踪显示已呈现的 ERB 文件。即使浏览器看到了所有这些,也没有发生页面更改!我真的没有明白这一点。显示是:

jQuery/javascript 代码:

$(document).on('page:change', function()

  // AJAX DataTable Moves Lots for bulk moves
  var lots_active = [];
  var movesindexlotstable = $('#movesindexlotstable').DataTable(
    responsive: true,
    autoWidth: false,
    pagingType: 'full',
    jQueryUI: false,
    processing: true,
    serverSide: true,
    ajax: 
      url: 'moves_indexlots.json',
      type: 'POST',
      contentType: 'application/json',
      dataType: 'json',
      data: function (d) 
        return JSON.stringify(d);
      
    ,
    columns: [
      "data": "name", className: null
    ],
    rowCallback: function (row, data) 
      if ($.inArray(data.DT_RowId, lots_active) !== -1) 
        $(row).addClass('active');
      
    
  );
  $('#movesindexlotstable tbody').on('click', 'tr', function () 
    var id = this.id;
    var index = $.inArray(id, lots_active);
    if (index === -1) 
      lots_active.push(id);
     else 
      lots_active.splice(index, 1);
    
    $(this).toggleClass('active');
  );
  // Ajax moves, select lots
  $('#movesindexlotsbutton').on('click', function () 
    var source = 'lots';
    $.post('/moves_indexrows.json',
        
          commit: 'Moves Lots',
          source: source,
          active: lots_active
        
    );
    return false;
  );

  // AJAX DataTable Moves Rows within Lots for bulk moves
  var rows_active = [];
  var movesindexrowstable = $('#movesindexrowstable').DataTable(
    responsive: true,
    autoWidth: false,
    pagingType: 'full',
    jQueryUI: false,
    processing: true,
    serverSide: true,
    ajax: 
      url: 'moves_indexrows.json',
      type: 'POST',
      contentType: 'application/json',
      dataType: 'json',
      data: function (d) 
        return JSON.stringify(d);
      
    ,
    columns: [
      "data": "name", className: null
    ],
    rowCallback: function (row, data) 
      if ($.inArray(data.DT_RowId, rows_active) !== -1) 
        $(row).addClass('active');
      
    
  );
  $('#movesindexrowstable tbody').on('click', 'tr', function () 
    var id = this.id;
    var index = $.inArray(id, rows_active);
    if (index === -1) 
      rows_active.push(id);
     else 
      rows_active.splice(index, 1);
    
    $(this).toggleClass('active');
  );
  // Ajax moves, select rows from selected lots
  $('#movesindexrowsbutton').on('click', function () 
    var source = 'rows';
    $.post('/moves_indexcars.json',
        
          commit: 'Moves Rows',
          source: source,
          active: rows_active
        
    );
    return false;
  );

);

RoR 代码:

class MovesController < ApplicationController

  before_action :check_if_associate

  def indexlots
    respond_to do |format|
      format.html
      format.json  render json: MovesIndexlotsDatatable.new(view_context) 
    end
  end

  def indexrows
    lots  = Array.new
    params[:active].map  |lot| id = lot[4..(lot.length-1)].to_i; lots << Lot.find(id); 
    respond_to do |format|
      format.html
      format.json  render json: MovesIndexrowsDatatable.new(view_context, lots) 
    end
  end

end

移动/indexlots.html.erb

<div class="row">
  <%= render partial: 'indexlots', layout: 'layouts/kac_label', locals: title: 'Moves Cars - Lots'  %>
</div>

移动/indexrows.html.erb

<div class="row">
  <%= render partial: 'indexrows', layout: 'layouts/kac_label', locals:  title: 'Moves Cars - Rows'  %>
</div>

moves/_indexlots.html.erb

<div class="form-group span8">
  <table id="movesindexlotstable" class="display dt-responsive no-wrap table-striped" cellspacing="0" >
    <thead>
    <tr>
      <th class="all"><b>Lot</b></th>
    </tr>
    </thead>
    <tbody>
    </tbody>
  </table>
  <div class='break_line'></div>
  <input type="submit" name="commit" value="Select Lots" id="movesindexlotsbutton" class="btn btn-primary kc-wide" data-no-turbolink data-disable-with="Processing">
  <%= link_to 'Home', '/', class: 'btn btn-primary kc-wide' %>
</div>

移动/_indexrows.html.erb

<div class="form-group span8">
  <table id="movesindexrowstable" class="display dt-responsive no-wrap table-striped" cellspacing="0" >
    <thead>
    <tr>
      <th class="all"><b>Rows</b></th>
    </tr>
    </thead>
    <tbody>
    </tbody>
  </table>
  <div class='break_line'></div>
  <input type="submit" name="commit" value="Select Rows" id="movesindexrowsbutton" class="btn btn-primary kc-wide" data-no-turbolink data-disable-with="Processing">
  <%= link_to 'Home', '/', class: 'btn btn-primary kc-wide' %>
</div>

日志:

...
Thin web server (v1.6.3 codename Protein Powder)
Maximum connections set to 1024
Listening on 127.0.0.1:3000, CTRL+C to stop


Started GET "/moves_indexlots" for 127.0.0.1 at 2016-02-20 16:58:32 -0500
  ActiveRecord::SchemaMigration Load (1.0ms)  SELECT "schema_migrations".* FROM "schema_migrations"
Processing by MovesController#indexlots as HTML
  Company Load (0.5ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."prefix" = $1 LIMIT 1  [["prefix", "ucf"]]
  Company Load (0.0ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."prefix" = $1  ORDER BY "companies"."id" ASC LIMIT 1  [["prefix", "ucf"]]
  CACHE (0.0ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."prefix" = $1 LIMIT 1  [["prefix", "ucf"]]
  Associate Load (1.0ms)  SELECT  "associates".* FROM "associates" WHERE "associates"."company_id" = $1 AND "associates"."id" = $2 LIMIT 1  [["company_id", 1], ["id", 74]]
  Role Load (0.5ms)  SELECT "roles".* FROM "roles" INNER JOIN "associates_roles" ON "roles"."id" = "associates_roles"."role_id" WHERE "associates_roles"."associate_id" = $1 AND (((roles.name = 'associate') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))  [["associate_id", 74]]
  CACHE (0.0ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."prefix" = $1 LIMIT 1  [["prefix", "ucf"]]
  Rendered moves/_indexlots.html.erb (8.0ms)
  Rendered moves/indexlots.html.erb within layouts/application (17.5ms)
Action#Controller is indexlots#moves
  Rendered layouts/_shim.html.erb (1.0ms)
  Role Load (0.5ms)  SELECT "roles".* FROM "roles" INNER JOIN "associates_roles" ON "roles"."id" = "associates_roles"."role_id" WHERE "associates_roles"."associate_id" = $1 AND (((roles.name = 'admin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))  [["associate_id", 74]]
  Rendered layouts/_navigation_links.html.erb (12.5ms)
  Rendered layouts/_navigation.html.erb (15.0ms)
  Rendered layouts/_messages.html.erb (1.0ms)
Completed 200 OK in 2386ms (Views: 2103.0ms | ActiveRecord: 7.5ms)


Started POST "/moves_indexlots.json" for 127.0.0.1 at 2016-02-20 16:58:35 -0500
Processing by MovesController#indexlots as JSON
  Parameters: "draw"=>1, "columns"=>["data"=>"name", "name"=>"", "searchable"=>true, "orderable"=>true, "search"=>"value"=>"", "regex"=>false], "order"=>["column"=>0, "dir"=>"asc"], "start"=>0, "length"=>10, "search"=>"value"=>"", "regex"=>false, "move"=>"draw"=>1, "columns"=>["data"=>"name", "name"=>"", "searchable"=>true, "orderable"=>true, "search"=>"value"=>"", "regex"=>false], "order"=>["column"=>0, "dir"=>"asc"], "start"=>0, "length"=>10, "search"=>"value"=>"", "regex"=>false
  Company Load (0.5ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."prefix" = $1 LIMIT 1  [["prefix", "ucf"]]
  Company Load (1.0ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."prefix" = $1  ORDER BY "companies"."id" ASC LIMIT 1  [["prefix", "ucf"]]
  CACHE (0.0ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."prefix" = $1 LIMIT 1  [["prefix", "ucf"]]
  Associate Load (0.5ms)  SELECT  "associates".* FROM "associates" WHERE "associates"."company_id" = $1 AND "associates"."id" = $2 LIMIT 1  [["company_id", 1], ["id", 74]]
  Role Load (1.0ms)  SELECT "roles".* FROM "roles" INNER JOIN "associates_roles" ON "roles"."id" = "associates_roles"."role_id" WHERE "associates_roles"."associate_id" = $1 AND (((roles.name = 'associate') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))  [["associate_id", 74]]
   (1.5ms)  SELECT COUNT(*) FROM "lots" WHERE "lots"."company_id" = $1  [["company_id", 1]]
  CACHE (0.0ms)  SELECT COUNT(*) FROM "lots" WHERE "lots"."company_id" = $1  [["company_id", 1]]
  Lot Load (0.5ms)  SELECT  "lots".* FROM "lots" WHERE "lots"."company_id" = $1  ORDER BY name asc LIMIT 10 OFFSET 0  [["company_id", 1]]
Completed 200 OK in 195ms (Views: 52.5ms | ActiveRecord: 7.5ms)


Started POST "/moves_indexrows.json" for 127.0.0.1 at 2016-02-20 16:58:41 -0500
Processing by MovesController#indexrows as JSON
  Parameters: "commit"=>"Moves Lots", "source"=>"lots", "active"=>["Row_64", "Row_29"]
  Company Load (0.5ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."prefix" = $1 LIMIT 1  [["prefix", "ucf"]]
  Company Load (0.0ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."prefix" = $1  ORDER BY "companies"."id" ASC LIMIT 1  [["prefix", "ucf"]]
  CACHE (0.0ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."prefix" = $1 LIMIT 1  [["prefix", "ucf"]]
  Associate Load (0.5ms)  SELECT  "associates".* FROM "associates" WHERE "associates"."company_id" = $1 AND "associates"."id" = $2 LIMIT 1  [["company_id", 1], ["id", 74]]
  Role Load (0.5ms)  SELECT "roles".* FROM "roles" INNER JOIN "associates_roles" ON "roles"."id" = "associates_roles"."role_id" WHERE "associates_roles"."associate_id" = $1 AND (((roles.name = 'associate') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))  [["associate_id", 74]]
  Lot Load (0.5ms)  SELECT  "lots".* FROM "lots" WHERE "lots"."company_id" = $1 AND "lots"."id" = $2 LIMIT 1  [["company_id", 1], ["id", 64]]
  Lot Load (0.5ms)  SELECT  "lots".* FROM "lots" WHERE "lots"."company_id" = $1 AND "lots"."id" = $2 LIMIT 1  [["company_id", 1], ["id", 29]]
   (1.0ms)  SELECT COUNT(*) FROM "rows" WHERE "rows"."company_id" = $1  [["company_id", 1]]
  Row Load (0.0ms)  SELECT "rows".* FROM "rows" WHERE "rows"."company_id" = $1 AND (lot_id = 64)  ORDER BY name asc  [["company_id", 1]]
  Row Load (0.5ms)  SELECT "rows".* FROM "rows" WHERE "rows"."company_id" = $1 AND (lot_id = 29)  ORDER BY name asc  [["company_id", 1]]
   (0.5ms)  SELECT COUNT(*) FROM "rows" WHERE "rows"."company_id" = $1 AND "rows"."id" IN (186, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144)  [["company_id", 1]]
  CACHE (0.0ms)  SELECT "rows".* FROM "rows" WHERE "rows"."company_id" = $1 AND (lot_id = 64)  ORDER BY name asc  [["company_id", 1]]
  CACHE (0.0ms)  SELECT "rows".* FROM "rows" WHERE "rows"."company_id" = $1 AND (lot_id = 29)  ORDER BY name asc  [["company_id", 1]]
  Row Load (0.5ms)  SELECT  "rows".* FROM "rows" WHERE "rows"."company_id" = $1 AND "rows"."id" IN (186, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144) LIMIT 10 OFFSET 0  [["company_id", 1]]
  CACHE (0.0ms)  SELECT COUNT(*) FROM "rows" WHERE "rows"."company_id" = $1 AND "rows"."id" IN (186, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144)  [["company_id", 1]]
Completed 200 OK in 213ms (Views: 86.3ms | ActiveRecord: 6.9ms)

MovesIndexlotsDatatable JSON:

""draw":1,"recordsTotal":57,"recordsFiltered":57,"data":["DT_RowId":"Row_64","name":"auction","DT_RowId":"Row_29","name":"Buying-Ctr","DT_RowId":"Row_30","name":"Buying-Ctr-Corrider A-H","DT_RowId":"Row_27","name":"Buying-Ctr-Corrider B-G","DT_RowId":"Row_31","name":"Buying-Ctr-Corrider C-F","DT_RowId":"Row_32","name":"Buying-Ctr-Corrider D-E","DT_RowId":"Row_36","name":"Buying-Ctr-Corrider E-L","DT_RowId":"Row_35","name":"Buying-Ctr-Corrider F-K","DT_RowId":"Row_34","name":"Buying-Ctr-Corrider G-J","DT_RowId":"Row_33","name":"Buying-Ctr-Corrider H-I"]"

MovesIndexrowsDatatable JSON:

""draw":1,"recordsTotal":92,"recordsFiltered":14,"data":["DT_RowId":"Row_133","name":" A","DT_RowId":"Row_134","name":" B","DT_RowId":"Row_135","name":" C","DT_RowId":"Row_136","name":" D","DT_RowId":"Row_137","name":" E","DT_RowId":"Row_138","name":" F","DT_RowId":"Row_139","name":" G","DT_RowId":"Row_140","name":" H","DT_RowId":"Row_141","name":" I","DT_RowId":"Row_142","name":" J"]"

【问题讨论】:

这个问题变得非常复杂。考虑到我目前的状态,我将问一个更直接、更简单的问题,看看我是否能得到回应。到目前为止,我不会关闭它,以防有人仍然可以帮助我并需要大量信息。谢谢。 【参考方案1】:

TL/DR:转换为使用 JavaScript 作为 SPA 和 Rails 作为 HTML/Data 微服务。

基本问题似乎是 Rails 不能完全了解并适应从 JavaScript 启动的操作。它将运行并使用 HTTP 200 渲染,但渲染只是不显示。我运行了跟踪,将标准操作与 JavaScript 启动的操作进行了比较,但在处理过程中找不到差异。我假设通常在启动时设置了一些内部变量,而不是通过 JavaScript 设置,这会导致此问题。但是,我没找到。

不过,我确实解决了这个问题。基本上我把这个过程变成了一个 SPA(单页应用程序)。第一个动作是标准的 Rails,但它会在用户的第一次交互或按钮单击时交给 JavaScript。从那时起,JavaScript 运行该过程,使用 AJAX POST 在一个操作中向 Rails 查询 HTML,在另一个操作中查询数据,从而将其作为微服务使用。 JavaScript 然后呈现结果页面,等待另一次点击,然后继续。最后一页提供了再次恢复到 Rails 标准处理的按钮。

这是我的故事,我会坚持下去。谢谢。

附言。我应该提一下,在一次性情况下,用 JS 触发一个动作对我来说有点用。我的问题是需要通过 JS 触发每一层屏幕,因为我每次都有信息从 JS 传递回操作。在一次性的情况下,我只是让动作发回控制使用:

render js: "window.location.assign(location.origin + '/item')" unless performed?

【讨论】:

以上是关于Rails 操作以状态 200 运行,但未访问模板且未触发 jQuery的主要内容,如果未能解决你的问题,请参考以下文章

Rails 6:JS绕过条件,每次访问运行代码

文件和打印共享资源处于联机状态,但未对脸接尝试做出反应

Rails 4 AbstractController::Metal 渲染状态!= 200(即 401、404)

已记录但未触发的操作

静态模板成员变量具有内部链接但未定义

常用状态码总结