Trejkaz Trejkaz - 1 year ago 308
Ruby Question

How do I resolve the deprecation warning "Method to_hash is deprecated and will be removed in Rails 5.1"

I'm trying to update to Rails 5, I'm getting the following deprecation warning:

DEPRECATION WARNING: Method to_hash is deprecated and will be removed in Rails 5.1, as
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: (called from column_header at /Data/Projects/portal/trunk/app/helpers/application_helper.rb:114)

The line the warning is on looks like this:

action: action_name,
params: params.merge({ order: key, page: nil })
title: "Sort by this field",
}) +

As you can see, I'm not calling
. Maybe Rails is. Maybe some other gem is. I have no way to tell, because they didn't think it was worth providing a stack trace. (Pro tip - it usually is worth providing a stack trace!)

So anyway, I followed the link, planning to find a replacement, and the
method does not appear to be deprecated
, but maybe they simply forgot to document deprecated status, so I can't really be sure.

So what am I supposed to do to clear this?

Answer Source

Use .to_h

You can call .to_h to get a safe hash, according to a comment on the Rails PR.

There are now three methods for converting parameters to a hash.

  • .to_h means "if I haven't called .permit, assume nothing is allowed."
  • .to_unsafe_h means "if I haven't called .permit, assume everything is allowed."
  • .to_hash is now ambiguous. Rails treats it like .to_unsafe_h, but prints a warning because you haven't explicitly said which of the two options above you wanted.

First, let's see what happens if you haven't called .permit. In a Rails 5.0 console:

> params ={yes: "y", no: "n"})

> params.to_h
{} # empty hash because nothing has been permitted

> params.to_unsafe_h
{"yes"=>"y", "no"=>"n"} # raw values with no warning; you asked for it

> params.to_hash
# (puts deprecation warning - if you want unsafe values, say so)
{"yes"=>"y", "no"=>"n"} # returns raw values

However, if you call .permit first, there will be no way to get the non-permitted values.

> params ={yes: "y", no: "n"})

> params = params.permit(:yes)
# (puts warning about unpermitted parameter :no)

> params.to_h
{"yes"=>"y"} # permitted values only

> params.to_unsafe_h
{"yes"=>"y"} # permitted values only

> params.to_hash
# (puts deprecation warning, but still safe)
{"yes"=>"y"} # permitted values only


  1. Always use .permit to whitelist the values you expect
  2. Use .to_h to ensure that if you forgot step 1, nothing will get through
  3. If you really want the raw values, don't call .permit and call .to_unsafe_hash
  4. Don't call .to_hash because that's now ambiguous
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download