rails/rails — pull request #13448 by chancancode (2013-12-22 11:22:38+00:00)
Title: Enum accessors now returns symbols instead of strings.

This was the behaviour in the original implementation, but it was changed in 44406d1e77061ce22effaae4698918c1f9f6271a.

From what I can tell, the motivation of 44406d1e77061ce22effaae4698918c1f9f6271a was to make enums work better with form inputs out of the box (i.e. takes either strings or symbols for its methods) without having to call `to_sym` on user input. (There doesn't seem to be strong reason that the accessor methods *should* return strings, as returning symbols would still allow it to work with form generation etc.)

That change however might cause surprises. The current documentation encourages user to define enum states with symbols (e.g. `enum status: [:active, :archived]`), so it leads to the reasonable (but incorrect) assumption that enums values are stored as symbols internally. When the user writes code like this based on that assumption, it might cause some surprises:

```ruby
class Conversation < ActiveRecord::Base
enum status: [:unread, :read, :archived, :deleted]

def open?
[:unread, :read].include? status
end
end
```

(I admit the example is a bit contrived as you'd probably write `unread? || read?` instead, but the purpose is the show a plausible example of what kind of code people might write when they expect enums to be symbols.)

There shouldn't be any security concerns with the `to_sym` usage here – if the record is in some invalid enum state for some reason, `nil` is returned from `key`, so the only time `to_sym` is called is when the record is in a valid enum state, in which case the symbol was already created during the declaration anyway.

IMO this makes the API surface smoother and more consistent as it always returns the same type (symbols) and hides the internal implementation details (which is really the internal implementation details of `HashWithIndifferentAccess` anyway).

cc @sanny @dhh