2

I am upgrading my Ruby 2.3.1 / Rails 4.2.5.1 to Rails 5.0.0.1 and I am encountering a strange error when running a controller spec for my following controller:

In my controller I have following code:

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

After updating the bundle to use Rails 5, when I ran the controller code I got following warning:

DEPRECATION WARNING: Method merge! is deprecated and will be removed in Rails 5.1, as ActionController::Parameters no longer inherits from hash. Using this deprecated behavior exposes potential security problems. If you continue to use this method you may be creating a security vulnerability in your app that can be exploited. Instead, consider using one of these documented methods which are not deprecated: http://api.rubyonrails.org/v5.0.0.1/classes/ActionController/Parameters.html

To fix this I changed

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

TO

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

and I am passing the params to my service class in following manner:

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

But with that change when I run the spec example it fails with error saying

 NoMethodError:
   undefined method `merge' for nil:NilClass

and the error trace points to the line where I made the change:

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

That is very weird because I tried printing params before that statement is evaluated and I am getting an object printed:

  >>>>>>>>>>>. 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>

Then why invoking merge on params is complaining about nil:NilClass.

I tried changing my updated code to

    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)

and it gets executed and my spec example passes.

I am not getting why then params = params.merge doesn't work.

Does anybody has any idea on what is causing this weird behaviour?

Another thing I tried is:

params = params

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

Now that fails with the same error

 undefined method `merge' for nil:NilClass 

So it looks like reassignment to params is the root cause behind this. If this sounds correct then is there any specific reason why params cannot be reassigned because documentation of ActionController::Parameters#merge(other_hash) method says

  Returns a new ActionController::Parameters with all keys from other_hash merges into current hash.

Thanks.

Rob
  • 14,746
  • 28
  • 47
  • 65
Jignesh Gohel
  • 6,236
  • 6
  • 53
  • 89

2 Answers2

0

I think, this should help you:

params = params.permit(:values, :from, :params).to_h.merge({
      acknowledger_user_id: acknowledger_user.id,
      alert_id: alert.id,
      acknowledgement_time: sms_sent_at
})
Oleksandr Holubenko
  • 4,310
  • 2
  • 14
  • 28
0

Params is Nil. You cannot .merge .permit on something that is not there. Make sure params is being initialized as an object first.