在控制器的动作中,`params = params.merge({})`引发NoMethodError:未定义的方法`merge'为零:NilClass

时间:2016-10-06 13:09:27

标签: merge params ruby-on-rails-5 nomethoderror actioncontroller

我正在将 Ruby 2.3.1 / Rails 4.2.5.1 升级到 Rails 5.0.0.1 ,我在运行控制器规范时遇到了一个奇怪的错误控制器:

在我的控制器中,我有以下代码:

class Api::InboundSmsCallbackController < ActionController::Base
  include Api::SmsCallbackHelpers
  include Api::ServiceErrorHelpers

  # GET    /inbound_sms_callback/alert_acknowledgement(.:format)
  def alert_acknowledgement

    ....
    ...

    params.merge!({
      acknowledger_user_id: acknowledger_user.id,
      alert_id: alert.id,
      acknowledgement_time: sms_sent_at
    })

    begin
      creation_service = AcknowledgementAlert::CreationService.new(params)
    rescue ServiceError => se
      render json: json_hash, status: status
      return
    end

    ....
    ...

    render json: json_hash, status: 200
  end

end

更新捆绑包以使用Rails 5后,当我运行控制器代码时,我收到了以下警告:

  

DEPRECATION WARNING:方法合并!已弃用,将被删除   在Rails 5.1中,不再是ActionController::Parameters         继承自哈希。使用此弃用行为会暴露潜在的安全问题。如果你继续使用这种方法   也许         在您的应用中创建可被利用的安全漏洞。相反,请考虑使用其中一种记录的方法   哪个是         不推荐使用:http://api.rubyonrails.org/v5.0.0.1/classes/ActionController/Parameters.html

为了解决这个问题,我改变了

    params.merge!({
      acknowledger_user_id: acknowledger_user.id,
      alert_id: alert.id,
      acknowledgement_time: sms_sent_at
    })

    params = params.merge({
      acknowledger_user_id: acknowledger_user.id,
      alert_id: alert.id,
      acknowledgement_time: sms_sent_at
    })

我将以下列方式将params传递给我的服务类:

creation_service = AcknowledgementAlert::CreationService.new(params.to_unsafe_h)

但是当我运行规范示例时,如果发生了这种变化,则会失败并显示

错误
 NoMethodError:
   undefined method `merge' for nil:NilClass

并且错误跟踪指向我进行更改的行:

    params = params.merge({
      acknowledger_user_id: acknowledger_user.id,
      alert_id: alert.id,
      acknowledgement_time: sms_sent_at
    })

这很奇怪,因为我在评估该语句之前尝试打印params并且我正在打印一个对象:

  >>>>>>>>>>>. params: <ActionController::Parameters {"message-timestamp"=>"2016-10-06 12:35:15 UTC", "msisdn"=>"919845128956", "text"=>"S3e9a6cE", "to"=>"12547836910", "controller"=>"api/inbound_sms_callback", "action"=>"alert_acknowledgement"} permitted: false>

那么为什么在merge上调用params抱怨nil:NilClass。

我尝试将更新的代码更改为

    ackn_params = params.merge({
      acknowledger_user_id: acknowledger_user.id,
      alert_id: alert.id,
      acknowledgement_time: sms_sent_at
    })

   creation_service = AcknowledgementAlert::CreationService.new(ackn_params.to_unsafe_h)

它会被执行,我的规范示例会通过。

我不明白为什么params = params.merge无效。

有没有人知道造成这种奇怪行为的原因是什么?

我尝试的另一件事是:

params = params

ackn_params = params.merge({
  acknowledger_user_id: acknowledger_user.id,
  alert_id: alert.id,
  acknowledgement_time: sms_sent_at
})

现在失败并出现相同的错误

 undefined method `merge' for nil:NilClass 

所以看起来重新分配到params是这背后的根本原因。如果这听起来不正确,那么由于params方法的documentation

而无法重新分配ActionController::Parameters#merge(other_hash),有任何具体原因吗?
  Returns a new ActionController::Parameters with all keys from other_hash merges into current hash.

感谢。

2 个答案:

答案 0 :(得分:0)

我认为,这应该可以帮到你:

params = params.permit(:values, :from, :params).to_h.merge({
      acknowledger_user_id: acknowledger_user.id,
      alert_id: alert.id,
      acknowledgement_time: sms_sent_at
})

答案 1 :(得分:0)

Params为零。您不能对不存在的内容进行.permit合并。确保先将参数初始化为对象。