Bug #9731
closed
Rails' HashWithIndifferentAccess is incompatible with Ruby's keyword arguments
Added by vrinek (Konstantinos Karachalios) over 10 years ago.
Updated over 5 years ago.
Description
Origin: https://github.com/rails/rails/issues/14643
In Ruby it is possible to use a POR Hash in place of keyword arguments, making the transition between using an options = {}
to keyword arguments easy.
The same is not true for HashWithIndifferentAccess and this makes it difficult to pass the params
hash directly to methods with keyword arguments.
Bug test¶
require 'active_support/hash_with_indifferent_access'
require 'minitest/autorun'
def sum(a: 0, b: 0)
a + b
end
class BugTest < MiniTest::Unit::TestCase
def setup
@normal_hash = {a: 18, b: 24} # just a hash
@indiff_hash = ActiveSupport::HashWithIndifferentAccess.new(@normal_hash)
end
def test_ruby_hash
assert_equal 42, sum(@normal_hash)
end
def test_hash_with_indifferent_access
assert_equal 42, sum(@indiff_hash)
end
end
Workaround¶
sum(@indiff_args.symbolize_keys)
VERSIONS¶
- ruby 2.0.0-p353 & activesupport 4.0.1
- ruby 2.1.0-p0 & activesupport 4.0.3
- ruby 2.1.1-p76 & activesupport 4.0.4, 3.2.17
- Has duplicate Bug #9732: Rails' HashWithIndifferentAccess is incompatible with Ruby's keyword arguments added
- Has duplicate Bug #9733: Rails' HashWithIndifferentAccess is incompatible with Ruby's keyword arguments added
- Has duplicate Bug #9734: Rails' HashWithIndifferentAccess is incompatible with Ruby's keyword arguments added
- Has duplicate Bug #9735: Rails' HashWithIndifferentAccess is incompatible with Ruby's keyword arguments added
Just to be clear this issue is not about HashWithIndifferentAccess
, it is about using hash with string keys to be used as keyword arguments (HashWithIndifferentAccess
store the keys as strings).
This same script would fail:
require 'minitest/autorun'
def sum(a: 0, b: 0)
a + b
end
class BugTest < MiniTest::Unit::TestCase
def setup
@hash_with_symbol_keys = {a: 18, b: 24}
@hash_with_string_keys = {'a' => 18, 'b' => 24}
end
def test_hash_with_symbol_keys
assert_equal 42, sum(@hash_with_symbol_keys)
end
def test_hash_with_string_keys
assert_equal 42, sum(@hash_with_string_keys)
end
end
I am negative for the proposal. My opinion is that you should not (or no longer) use strings as keywords.
For transition purpose, ActiveSupport (or something else) can add a method to convert strings keys to symbol keys.
Matz.
Yes, I agree with you. I'm also not positive to changing keyword arguments to receive even strings and symbols, but I thought OP should request this feature here since it is not Rails specific, as he would have the same behavior with a normal hash using string keys.
As soon we only support Ruby 2.2 we can store the keywords as symbols, but until there, we can't change HashWithIndifferentAccess
to use symbols or we are opening Rails applications to receive DDoS attacks.
We already have this method to convert strings keys to symbol keys. It is called symbolize_keys
. And in my opinion it is fine to use if you know what is doing. I would never call symbolize_keys
in request parameters for example. At least not until my application is running with the new symbol GC.
I agree with the above comments. Probably waiting for Ruby 2.2 would be the best course of action here.
I will try nevertheless create a workaround by utilising Method#parameters
to feed the usual params.slice(*args).symbolize_keys
in a clever and unobstructive way. Hints/ideas are welcome.
- Status changed from Open to Closed
Also available in: Atom
PDF
Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0