In Rails 4.1, how to find records by enum symbol?

27,253

Solution 1

ActiveRecord::Enum provides scopes based on its values.

Just try:

Conversation.active

or

Conversation.archived

Of course, you can create your own scopes as Kyle Decot mentioned.

Solution 2

This works great:

Conversation.where("conversation.status = ?", Conversation.statuses[:active])

For some reason this does NOT work:

Conversation.where(status: :active) #searches for NULL
Conversation.where(status: 'active') #searches for status=0 no matter what the enum

Update

All the above statements work with Rails 5. Happy coding!

Solution 3

ActiveRecord::Enum provides built-in scopes based on the values so you can simply do:

Conversation.active
Conversation.archived

Solution 4

Conversation.where(status: Conversation.statuses[:active])

Solution 5

Did you try Conversation.where(status: [:active, :archived]) ? As listed here.

Share:
27,253

Related videos on Youtube

Abdulaziz
Author by

Abdulaziz

Updated on March 01, 2020

Comments

  • Abdulaziz
    Abdulaziz about 4 years

    Assume I have this model:

    class Conversation < ActiveRecord::Base
      enum status: [ :active, :archived ]
    end
    

    How can I find all active conversations without using the numeric value of the enum or without having to iterate over each conversation?

    I tried doing Conversation.where(status: :active), but it didn't yield any results.

    The only solution comes to mind is to iterate over all conversations and select the active ones, but it doesn't look like a good solution.

    Conversation.all.select {|conversation| conversation.active? }  
    

    Is there anything I can do about this?

  • joshua.paling
    joshua.paling over 9 years
    No need to create a new instance - Conversation.statuses[:active] should work
  • Avael Kross
    Avael Kross about 9 years
    ASAP, enum creates scopes like this by default, so if you have enum status: %i[active archived], you already have .active and .archived scopes.
  • pragma
    pragma almost 9 years
    Kensuke Naito's solution below is much better
  • Logar
    Logar about 8 years
    This one never worked for me. Everytime i have to match every record with the same state as my object I have to do Conversation.where(status: Conversation.statuses[my_conversation.status]). Any idea why it doesn't work ?
  • Shifa Khan
    Shifa Khan about 8 years
    @Logar Maybe isn't supposed to.. Check github.com/rails/rails/issues/19964
  • Logar
    Logar about 8 years
    Hehe, I got lured by documentation. At least now I know !
  • MegaTux
    MegaTux about 8 years
    Conversation.where(status: [Conversation.statuses[:active], Conversation.statuses[:archived]])
  • MegaTux
    MegaTux about 8 years
    Nice!, this way I can do "or" expressions: Conversation.where(status: [Conversation.statuses[:active], Conversation.statuses[:archived]])
  • Mirror318
    Mirror318 almost 8 years
    Note that Rails 5 will allow all these statements to work. Woo!
  • Chris Nicola
    Chris Nicola almost 8 years
    Not really a solution if you are passing that type value as a string say via an API request or query string value.
  • rubyprince
    rubyprince about 7 years
    The answer can be rewritten as Conversation.where(status: Conversation.statuses[:active]). No need for strings.
  • Greg Blass
    Greg Blass almost 7 years
    Just switched back to work on a Rails 4 project and thought I was going nuts. Thank you for noting that these are Rails 5 conventions.
  • rmcsharry
    rmcsharry over 6 years
    Also, if you wanted the opposite (ie. all records where status is anything other than active): Conversation.where.not(status: Conversation.statuses[:active])
  • Abe Voelker
    Abe Voelker over 6 years
    Unfortunately Rails 5 doesn't fix querying through a parent (e.g. Person.joins(:conversations).where(conversations: {status: :active}) errors out). Have to use the first method for that yet (Person.joins(:conversations).where(conversations: {status: Conversation.statuses[:active]})).