1

I have a Door object that has a state attribute of type string. It can only be one of these elements: %w[open shut locked].

Are there any implications or reasons for using strings over symbols?

door.update_attributes(state: :open)
door.update_attributes(state: 'open')

In Rails 4 we can do this:

Door.order(created_at: :desc)

So why shouldn't I do this?

Door.where(state: :open) # vs state: 'open'

Are they equivalent for all intents and purposes? I prefer to use a symbol because it looks cleaner, and in the DB, a symbol will be a string anyway.

Jumbalaya Wanton
  • 1,601
  • 1
  • 25
  • 47

2 Answers2

3

The difference between using a symbol and a string is that strings are garbage collected if that specific object is no longer being referred to by a variable or held in some collection (such as a Hash or an Array).

So if they are not in a collection that still exists, they will eventually be garbage collected, but Symbols are forever for the life of the program.

If your key no longer references the 'open' string, that string is eligible for garbage collection, but if it was a symbol for the value, it is no longer referenced by that key, but it will linger in memory.

This can be a Very Bad Thing™

vgoff
  • 10,980
  • 3
  • 38
  • 56
  • 1
    Symbols vs. strings are one of the things in Ruby we need to be aware of; Every language has similar trade-offs for features that we need to be aware of. I consider it part of the "joy" of programming. – the Tin Man Jul 25 '13 at 00:53
3

Your instincts are right, IMHO.

Symbols are more appropriate than strings to represent the elements of an enumerated type because they are immutable. While it's true that they aren't garbage collected, unlike strings, there is always only one instance of any given symbol, so the impact is minimal for most state transition applications. And, while the performance difference is minimal as well for most applications, symbol comparison is much quicker than string comparison.

See also Enums in Ruby

Community
  • 1
  • 1
Peter Alfvin
  • 28,599
  • 8
  • 68
  • 106