【问题标题】:Rails 5 jQuery .ajax method data formatRails 5 jQuery .ajax 方法数据格式
【发布时间】:2017-09-13 09:26:01
【问题描述】:

升级到 Rails 5 后,我的 jQuery .ajax 请求出现问题。我相信这与(有些)新的强参数有关。我收到以下错误:

ArgumentError (When assigning attributes, you must pass a hash as an argument.):

我认为我在我的 .ajax 请求中错误地设置了我的数据包(使用 Coffeescript)。

或者可能是我信任的参数无法正常工作。

使用 byebug,我的控制器的第一行似乎没问题,但它在第二行失败:@prospect.update(prospect_params[:status])。这是 byebug 中的 @_params 变量:

1: @_params = <ActionController::Parameters {"prospect"=><ActionController::Parameters {"id"=>"16", "status"=>"inactive"} permitted: false>, "controller"=>"prospects", "action"=>"update_status"} permitted: false>

这是来自我的控制器的 sn-ps 和 Coffescript

控制器

  # PUT /prospects/update_status
  def update_status
    @prospect = Prospect.find(params[:id])
    @prospect.update(prospect_params[:status])

    respond_to do |format|
      if @prospect.update_attributes(prospect_params)
        format.json { head :no_content }
      else
        format.json { render json: @prospect.errors, status: :unprocessable_entity }
      end
    end
  end

...

  private
  # Use callbacks to share common setup or constraints between actions.
  def set_prospect
    @prospect = Prospect.find(params[:id])
  end

  # Only allow a trusted parameter "white list" through.
  def prospect_params
    params.require(:prospect).permit(:name, :status, :priority, :id)
  end

咖啡脚本

    # Update prospects active list when a toggle switch is clicked
    $("#prospects_list").on "change", ".js-switch", ->
        prospect_id = $(this).parent('form').find('input[name="prospect[id]"]').val()
        if @checked
            status = 'active'
        else
            prospect_status = 'inactive'
        # Get parent TR
        tr = $(this).closest('tr')
        # Update prospect using Ajax
        $.ajax
            url: '/prospects/update_status'
            type: 'POST'
            data: { prospect: {id: prospect_id, status: prospect_status } }
            dataType: 'json'
            success: (data) ->
                return
            false

【问题讨论】:

  • 您希望 params 哈希看起来像什么?

标签: jquery ruby-on-rails ajax coffeescript ruby-on-rails-5


【解决方案1】:

首先问自己是否真的需要一个特定的路由来更新状态,或者这是否应该是对规范更新路由的请求:

PATCH /prospects/:id

在这种情况下,您应该更改 AJAX 处理程序:

# Update prospects active list when a toggle switch is clicked
$("#prospects_list").on "change", ".js-switch", ->
    prospect_id = $(this).parent('form').find('input[name="prospect[id]"]').val()
    if @checked
      status = 'active'
    else
      prospect_status = 'inactive'
    # Get parent TR
    tr = $(this).closest('tr')
    # Update prospect using Ajax
    $.ajax
      url: '/prospects/' + prospect_id
      type: 'PATCH' # Not POST!
      data: { prospect: { status: prospect_status } }
      dataType: 'json'
      success: (data) ->
          return
      false

如果您出于某种原因需要特定的方法,您可以通过将 :id 移动到路径而不是参数来修复它。

# config/routes.rb
resources :prospects do
  member do
    patch :update_status
  end
end

# PATCH /prospects/:id/update_status
def update_status
  @prospect = Prospect.find(params[:id])
  respond_to do |format|
    if @prospect.update_attributes(prospect_params)
      format.json { head :no_content }
    else
      format.json { render json: @prospect.errors, status: :unprocessable_entity }
    end
  end
end

# ...

def prospect_params
  params.require(:prospect).permit(:name, :status, :priority)
end

# coffeescript
url: '/prospects/' + prospect_id  +'/update_status'

使用@prospect.update(prospect_params[:status]) 会更新记录两次,并且会避开强参数,因此会引发异常。

【讨论】:

  • 更高版本的 Rails 使用 PATCH 而不是 PUT,因为语义匹配更新记录更好。
  • 感谢您接受双重更新。我修好了。接下来我将尝试使用 PATCH,但现在我想要尽可能少的更改,因为我必须在许多 jquery 调用中复制它。
  • 如果你在复制这个,那么你做错了。定义一个简单的 JavaScript 函数,它接受更新(一个对象)并返回 promise object (return $.ajax(...))。然后在 promise 对象上使用 .done 定义回调。
【解决方案2】:

感谢 Зелёный 和 max 让我朝着正确的方向前进。这是我使用的有效方法。我只需要对控制器进行一点改动

控制器

# PUT /prospects/update_status
def update_status
  @prospect = Prospect.find(prospect_params[:id])
  respond_to do |format|
    if @prospect.update(status: prospect_params[:status])
      format.json { head :no_content }
    else
      format.json { render json: @prospect.errors, status: :unprocessable_entity }
    end
  end
end

【讨论】:

    【解决方案3】:

    您传递参数的值。

    查看错误信息you must pass a hash as an argument.

    @prospect.update(prospect_params[:status])
    # here is you pass a value of status key, that's not a hash
    # {"id"=>"16", "status"=>"inactive"} 
    # prospect_params[:status] => "inactive"
    

    只使用:

    @prospect.update(prospect_params)
    # that's pass a hash
    # prospect_params => {"id"=>"16", "status"=>"inactive"}
    

    或者:

    @prospect.update(status: prospect_params[:status])
    

    【讨论】:

    • 谢谢。虽然这有点令人困惑,因为我不太了解哈希是什么,但它帮助我找到了正确的语法。我会在另一个答案中发布。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-03
    • 1970-01-01
    • 2017-03-30
    相关资源
    最近更新 更多