How to store and compare :symbols in an ActiveRecord (Ruby on Rails)

seanyboy picture seanyboy · Jan 27, 2012 · Viewed 17.2k times · Source

I thought it would be good to populate a status field in an activeRecord table using constants. However, when it comes to checking if this status has a particular status, I'm having trouble.

If I do the following,

e = Mytable.new
e.status = :cancelled
e.save

then refind the record and try and compare my status to the symbol, the check fails. I have some output from the console to show this.

irb(main):060:0> e.status.eql?("cancelled")
=> true
irb(main):061:0> e.status.eql?(:cancelled)
=> false
irb(main):062:0> e.status == :cancelled
=> false
irb(main):063:0> e.status == "cancelled"
=> true
irb(main):064:0> e.status == :cancelled.to_s
=> true

Is there a better way of holding a status in a record? Is there a way of testing if a current field value is equal to the :symbol without converting the :symbol to a string? I'm thinking there may be an operator I'm not aware of.

Answer

jiehanzheng picture jiehanzheng · May 4, 2014

With Rails 4.1.0, you'd probably want to use Active Record enums.

To quote the official release notes:

class Conversation < ActiveRecord::Base
  enum status: [ :active, :archived ]
end
 
conversation.archived!
conversation.active? # => false
conversation.status  # => "archived"
 
Conversation.archived # => Relation for all archived Conversations
 
Conversation.statuses # => { "active" => 0, "archived" => 1 }