Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: How do I create a default value for attributes in Rails activerecord's model? [duplicate]

You can set a default option for the column in the migration

....
add_column :status, :string, :default => "P"
....

OR

You can use a callback, before_save

class Task < ActiveRecord::Base
  before_save :default_values
  def default_values
    self.status ||= 'P' # note self.status = 'P' if self.status.nil? might be safer (per @frontendbeauty)
  end
end

Because I encountered this issue just a little while ago, and the options for Rails 3.0 are a bit different, I'll provide another answer to this question.

In Rails 3.0 you want to do something like this:

class MyModel < ActiveRecord::Base
  after_initialize :default_values

  private
    def default_values
      self.name ||= "default value"
    end
end

When I need default values its usually for new records before the new action's view is rendered. The following method will set the default values for only new records so that they are available when rendering forms. before_save and before_create are too late and will not work if you want default values to show up in input fields.

after_initialize do
  if self.new_record?
    # values will be available for new record forms.
    self.status = 'P'
    self.featured = true
  end
end

You can do it without writing any code at all :) You just need to set the default value for the column in the database. You can do this in your migrations. For example:

create_table :projects do |t|
  t.string :status, :null => false, :default => 'P'
  ...
  t.timestamps
end

Hope that helps.


The solution depends on a few things.

Is the default value dependent on other information available at creation time? Can you wipe the database with minimal consequences?

If you answered the first question yes, then you want to use Jim's solution

If you answered the second question yes, then you want to use Daniel's solution

If you answered no to both questions, you're probably better off adding and running a new migration.

class AddDefaultMigration < ActiveRecord::Migration
  def self.up
     change_column :tasks, :status, :string, :default => default_value, :null => false
  end
end

:string can be replaced with any type that ActiveRecord::Migration recognizes.

CPU is cheap so the redefinition of Task in Jim's solution isn't going to cause many problems. Especially in a production environment. This migration is proper way of doing it as it is loaded it and called much less often.


I would consider using the attr_defaults found here. Your wildest dreams will come true.


Just strengthening Jim's answer

Using presence one can do

class Task < ActiveRecord::Base
  before_save :default_values
  def default_values
    self.status = status.presence || 'P'
  end
end