Ruby on Rails ActiveRecord: how to save object state?

I have a User model that has state. The state can be any of the following: ['unverified', 'active', 'deleted']

What's the best way to store the state of an object in a database?

Should I create three boolean fields? It wouldn't make a lot of sense, as I could easily expand the number of states, and only one state can be "true" at a time.

Should I use the state_machine gem just for simple toggling of constant values?

Or is there another common way, best practice or simple stone for this kind of work?

+3


source to share


5 answers


A very simple solution I used for this:

In your migration

add_column :users, :state, :string

      

In your model

class User < ActiveRecord::Base

  STATES = %w{ unverified active deleted }

  STATES.each do |state|
    define_method("#{state}?") do
      self.state == state
    end

    define_method("#{state}!") do
      self.update_attribute(:state, state)
    end
  end
end

      



Then you can call

@user.active? # => returns true/false

      

or

@user.active! # => sets the users state to active

      

+17


source


If you are using Rails3 with MySQL database you can use enum_column . It provides the column :enum

to be used in migrations as well as a validation method. It also provides the enum_select view helper.



+3


source


You can use an enumerated type to store state as a simple integer. I usually use the active_enum gem to keep it simple. It will look something like this.

class User

  # An enumerated type representing the current state of the user
  enumerate :state do
    value name: "unverified"
    value name: "active"
    value name: "deleted"
  end

end

      

This will allow you to check the status like this

# check if active
user.state?(:active)

      

Just make sure you have an integer named field state

(or whatever you want to call an enumerated type) in your table User

.

See the gem documentation for details .

+2


source


I would leave it as nil, "active", "deleted". If you want to have additional process interceptors on state switching, such as sent emails, then the state_machine gem will be useful. Also, if you want to have additional analytics, like when someone went from unverified to active, it can be useful to have "active_on_date" and store that as the date and time when the transition will occur.

+1


source


Don't use boolean fields.

If the state names are like "key" and are unlikely to change, you can simply store them as text fields in the database. Just add a carry with

add_column :users, :state, :string

      

When you save your object, it will take user.state and store the character as the string "unverified", "active", etc.

If the states are likely to be renamed at some point, you can put them in your own table and create your own activerecord model for them instead of using the symbol. to do

rails g model State name:string

      

rails will create a model file and transfer them. Then change the migration as follows:

add_column :users, :state_id, :integer

      

You can populate the list of states with unchecked, active, etc. either directly to sql or via seed or an existing migration. You can also create a foreign key between them.

Then in your code, to set the state, you have to use this:

user.state = State.find_by_name(:unverified)

      

+1


source







All Articles