Rails 5: AJAX 未触发 save/load 回调 (PATCH / GET)

Rails 5: AJAX not triggering for save/load callbacks (PATCH / GET)

我有点难以实现 AJAX 和 JSON 响应。我有这个 控制器

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" =  LIMIT   [["id", 2], ["LIMIT", 1]]
  Common::DatatableState Load (1.5ms)  SELECT  "common_datatable_states".* FROM "common_datatable_states" WHERE "common_datatable_states"."user_id" =  AND "common_datatable_states"."name" =  ORDER BY "common_datatable_states"."id" ASC LIMIT   [["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" =  LIMIT   [["id", 2], ["LIMIT", 1]]
  Common::DatatableState Load (1.6ms)  SELECT "common_datatable_states"."state" FROM "common_datatable_states" WHERE "common_datatable_states"."user_id" =  AND "common_datatable_states"."name" =   [["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 工作?

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

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

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