问题
I am using enum
to map integers in my database to semantic values in my ruby code, however I noticed that the keys that it uses are strings. When I checked the type of the hash, I discovered that it was an ActiveSupport::HashWithIndifferentAccess
, not a standard Hash
, which makes sense, but lead to the question of why Rails chose to store and compare the values as strings, not symbols, internally.
The documentation states:
Internally symbols are mapped to strings when used as keys in the entire writing interface
Symbols are usually used in hashes because of their fast comparison, but Rails has chosen to use strings instead. Why have they chosen to do this, and how significant is the difference in performance?
回答1:
Why have they chosen to do this
ActiveSupport::HashWithIndifferentAccess
is mainly used to handle parameters coming from outside. Symbols are stored in the ruby heap and in general, they are never released back to the system.
Using symbols as keys in something that gets keys from the outside, leads to the vulnerability against OutOfMemory
attacks ([D]DoS
, sending queries with randomly generated parameters names.) That’s why strings were chosen, AFAIU. For 100% assurance ask DHH.
how significant is the difference in performance?
Use Benchmark to check. This site is not supposed to be a “please do benchmarks for me” site.
回答2:
In the past, there were some implementations that were unable to collect symbols. IOW, a symbol, once created, would stay in memory until the end of time the process (which for a server process like a Rails app, can be months). Up until three weeks ago, YARV, the most popular implementation, happened to be one of those.
Ergo, you could DoS a Ruby system running one of those vulnerable implementations by generating lots of symbols, and since Rails uses HWIA for request params (which are fully under the attacker's control), among others, it is quite trivial to do so.
Now, that every single implementation supports collecting symbols (JRuby and Rubinius supported it years ago, YARV supports it since 2.4.0), that implementation strategy may change … or not: never change a running system.
来源:https://stackoverflow.com/questions/41592312/why-does-rails-hashwithindifferentaccess-store-keys-as-strings-and-not-symbol