【问题标题】:Rails 5: AJAX not triggering for save/load callbacks (PATCH / GET)Rails 5:AJAX 未触发保存/加载回调(PATCH / GET)
【发布时间】:2017-10-12 02:41:35
【问题描述】:

我在用 JSON 响应实现 AJAX 时有点卡住了。我有这个控制器

class Common::DatatablesStatesController < ApplicationController

  def update
    datatables_state.update(datatable_states_params)
    render json: datatables_state
  end

  def show
    render json: datatables_state
  end

  private
  def datatable_states_params
    params.require(:common_datatable_state).permit(:user_id, :name, :state)
  end

  def datatables_state
    @datatables_state ||= current_user.datatables_states
                          .where(name: params[:id]).first_or_create
  end
end

它基本上检查参数记录是否存在,如果存在,则更新state 列,如果不存在 - 创建新记录(current_user ID,来自下面 JS 的 contname,状态)

我的Coffeescript现在是这样的:

$ ->
  $('#data-table').DataTable
    ajax: $('#data-table').data('source')
    serverSide: true
    stateSave: true
    contname = $('#data-table').attr('data-controller-name')
    'stateSaveCallback': (settings, data) ->
      $.ajax
        'url': '/common/datatables_states/' + contname + '.json'
        'data':
          'user_id': user_id
          'name': contname
          'state': data
        'dataType': 'json'
        'type': 'PATCH'
        success: ->
      return
    'stateLoadCallback': (settings, callback) ->
      $.ajax
        'url': '/common/datatables_states/' + contname + '.json'
        'data':
          'name': contname
          'state': data
        'async': false
        'dataType': 'json'
        'type': 'GET'
        'success': (json) ->
          callback json
          return
      return
  return

我很确定我的 JS 部分有问题,因为我的控制台中没有发生任何事情,但不知道它是什么。我很乐意提供任何帮助。谢谢!

更新

我的路线如下所示:

namespace :common do
  resources :datatables_states, only: [:update, :show]
end

rails routes

 common_datatables_state GET    (/:locale)/common/datatables_states/:id(.:format)        common/datatables_states#show {:locale=>/en|lv/}
                                   PATCH  (/:locale)/common/datatables_states/:id(.:format)        common/datatables_states#update {:locale=>/en|lv/}
                                   PUT    (/:locale)/common/datatables_states/:id(.:format)        common/datatables_states#update {:locale=>/en|lv/}

基本上的想法是将 data-controller-name 从视图中作为 ID 传递。

更新2

我切换到 vanila JS,因为我怀疑我的 Coffeescript 有问题。这是我放入 JS 文件的内容:

jQuery(document).ready(function() {
    $('#data-table').DataTable(
            {
                "processing": true,
                "serverSide": true,
                "ajax": $('#data-table').data('source'),
                stateSave: true,
                "stateSaveCallback": function (settings, data) {
                    // Send an Ajax request to the server with the state object
                    $.ajax( {
                        "url": "/common/datatables_states/campaigns_index.json", //Test link with :ID campaigns_index.json
                        "data": {"name":"campaigns_index", "state": data} ,
                        "dataType": "json",
                        "type": "PATCH",
                        "success": function () {}
                    } );
                },
                   stateLoadCallback: function (settings, callback) {
                      $.ajax( {
                         url: '/common/datatables_states/campaigns_index.json',
                         async: false,
                         dataType: 'json',
                         type: 'GET',
                         success: function (json) {
                         callback( json );
                         }
                    } );
                 }
            }
    );
});

这就是我现在在控制台中看到的:

Started PATCH "/common/datatables_states/campaigns_index.json" for 10.0.2.2 at 2017-05-12 20:27:03 +0000
Processing by Common::DatatablesStatesController#update as JSON
  Parameters: {"name"=>"campaigns_index", "state"=>{"time"=>"1494620823501", "start"=>"0", "length"=>"10", "order"=>{"0"=>["0", "asc"]}, "search"=>{"search"=>"", "smart"=>"true", "regex"=>"false", "caseInsensitive"=>"true"}, "columns"=>{"0"=>{"visible"=>"true", "search"=>{"search"=>"", "smart"=>"true", "regex"=>"false", "caseInsensitive"=>"true"}}, "1"=>{"visible"=>"true", "search"=>{"search"=>"", "smart"=>"true", "regex"=>"false", "caseInsensitive"=>"true"}}, "2"=>{"visible"=>"true", "search"=>{"search"=>"", "smart"=>"true", "regex"=>"false", "caseInsensitive"=>"true"}}}}, "id"=>"campaigns_index"}
  User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 2], ["LIMIT", 1]]
  Common::DatatableState Load (1.5ms)  SELECT  "common_datatable_states".* FROM "common_datatable_states" WHERE "common_datatable_states"."user_id" = $1 AND "common_datatable_states"."name" = $2 ORDER BY "common_datatable_states"."id" ASC LIMIT $3  [["user_id", 2], ["name", "campaigns_index"], ["LIMIT", 1]]
Completed 400 Bad Request in 15ms (ActiveRecord: 2.0ms)


ActionController::ParameterMissing (param is missing or the value is empty: common_datatable_state):

app/controllers/common/datatables_states_controller.rb:14:in `datatable_states_params'
app/controllers/common/datatables_states_controller.rb:4:in `update'
app/controllers/application_controller.rb:45:in `set_current_user'

更新 3

我正在尝试为我的 DataTables 1.10.13 实现 stateLoadCallback

我将控制器操作更改为此,因此它仅选择 state

def show
  state = current_user.datatables_states.where(name: params[:id]).select(:state)
  render json: state
end

然后在 JS 中我这样做,这有点根据文档:

 stateLoadCallback: function (settings, callback) {
                      $.ajax( {
                         url: '/common/datatables_states/campaigns_index.json',
                         async: false,
                         dataType: 'json',
                         type: 'GET',
                         success: function (json) {
                         callback( json );
                         }
                    } );
                 }

但是在终端我没有得到state 回复:

Started GET "/common/datatables_states/campaigns_index.json" for 10.0.2.2 at 2017-05-14 10:02:03 +0000
Processing by Common::DatatablesStatesController#show as JSON
  Parameters: {"id"=>"campaigns_index"}
  User Load (0.9ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 2], ["LIMIT", 1]]
  Common::DatatableState Load (1.6ms)  SELECT "common_datatable_states"."state" FROM "common_datatable_states" WHERE "common_datatable_states"."user_id" = $1 AND "common_datatable_states"."name" = $2  [["user_id", 2], ["name", "campaigns_index"]]
Completed 200 OK in 83ms (Views: 25.3ms | ActiveRecord: 9.6ms)

state 列的类型是 JSON,当我导航到 http://localhost:3000/en/common/datatables_states/campaigns_index.json 时,我看到了:

[
  {
    "id": null,
    "state": "{\"time\":\"1494761473541\",\"start\":\"0\",\"length\":\"10\",\"order\":{\"0\":[\"0\",\"asc\"]},\"search\":{\"search\":\"\",\"smart\":\"true\",\"regex\":\"false\",\"caseInsensitive\":\"true\"},\"columns\":{\"0\":{\"visible\":\"true\",\"search\":{\"search\":\"\",\"smart\":\"true\",\"regex\":\"false\",\"caseInsensitive\":\"true\"}},\"1\":{\"visible\":\"true\",\"search\":{\"search\":\"\",\"smart\":\"true\",\"regex\":\"false\",\"caseInsensitive\":\"true\"}},\"2\":{\"visible\":\"true\",\"search\":{\"search\":\"\",\"smart\":\"true\",\"regex\":\"false\",\"caseInsensitive\":\"true\"}}}}"
  }
]

更新 3.1。

我加了state = current_user.datatables_states.where(name: params[:id]).select(:state).first

我现在有了这个:

{
  "id": null,
  "state": "{\"time\":\"1494910215056\",\"start\":\"0\",\"length\":\"10\",\"order\":{\"0\":[\"0\",\"asc\"]},\"search\":{\"search\":\"\",\"smart\":\"true\",\"regex\":\"false\",\"caseInsensitive\":\"true\"},\"columns\":{\"0\":{\"visible\":\"true\",\"search\":{\"search\":\"\",\"smart\":\"true\",\"regex\":\"false\",\"caseInsensitive\":\"true\"}},\"1\":{\"visible\":\"true\",\"search\":{\"search\":\"\",\"smart\":\"true\",\"regex\":\"false\",\"caseInsensitive\":\"true\"}},\"2\":{\"visible\":\"true\",\"search\":{\"search\":\"\",\"smart\":\"true\",\"regex\":\"false\",\"caseInsensitive\":\"true\"}}}}"
}

当我将show 更改为:

def show
  state = current_user.datatables_states.where(name: params[:id]).select(:state).first
  my_hash = JSON.parse(state)
  render json: JSON.pretty_generate(my_hash)
end

并得到这个错误:

TypeError (no implicit conversion of nil into String):
app/controllers/common/datatables_states_controller.rb:10:in `show'
app/controllers/application_controller.rb:45:in `set_current_user'

我应该怎么做才能让 stateLoadCallback 正常工作?

【问题讨论】:

  • 您确定您的路线设置正确吗?您可以发布您的routes.rb 或调用rake routes 的结果吗?
  • @xlts 请参阅上面的更新。
  • @xlts 你能检查我上面的更新 2,好吗?我改用 vanila JS,现在我开始在控制台中看到一些东西。

标签: javascript ruby-on-rails ajax coffeescript


【解决方案1】:

您添加的错误表明没有传递common_datatable_state 参数,这是因为您如何定义强参数(datatable_state_params 方法)。尝试像这样更改 ajax 调用中的 data 字段:

"data": {"common_datatable_state":{"name":"campaigns_index", "state": data}}

【讨论】:

  • 谢谢,总的来说,您是对的,我接受并支持。就我而言,我必须这样做"data": {"common_datatable_state":{"user_id": "2", "name":"campaigns_index", "state": data}} ,
  • 能否请您检查我上面的更新 3,我尝试实现 show 方法以从数据库中取回 state 数据。
  • 嗯,你可以看到输出,所以这只是调试的问题。首先,您可能想在选择数据表状态时调用.first - 现在您正在返回一个数组,我想您应该只得到单个对象。至于输出,您可以看到它是一个打包在字符串中的 JSON。您可以尝试调用JSON.parse(query_result) 来获取可以呈现为漂亮json 的ruby 哈希(参见ruby-doc.org/stdlib-2.0.0/libdoc/json/rdoc/JSON.html
  • 谢谢。我正在尝试遵循您的建议,但是我收到了TypeError (no implicit conversion of nil into String) 你能检查我的更新 3.1。上面,好吗?还有一件事 - 我不应该以某种方式摆脱 "id": null 吗?
  • 错误告诉你第 10 行的内容是 nil - 尝试调试它,例如与pry 宝石。要摆脱"id": null,您应该准确指定要序列化的内容。例如,您可以以这种方式执行render json: { state: state["state"] } 或其他操作
【解决方案2】:

我认为问题出在where(name: params[:id]),你能检查一下这里的参数

【讨论】:

  • 检查参数是什么意思?想法是从视图中获取 data-controller-name 并将其传递为 id - 请在上面的更新中查看我的路线。
  • 你能检查我上面的更新 2,好吗?我改用 vanila JS,现在我开始在控制台中看到一些东西。
猜你喜欢
  • 1970-01-01
  • 2016-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多