How to Set Default Values in Rails

Rails: How can I set default values in ActiveRecord?

There are several issues with each of the available methods, but I believe that defining an after_initialize callback is the way to go for the following reasons:

  1. default_scope will initialize values for new models, but then that will become the scope on which you find the model. If you just want to initialize some numbers to 0 then this is not what you want.
  2. Defining defaults in your migration also works part of the time... As has already been mentioned this will not work when you just call Model.new.
  3. Overriding initialize can work, but don't forget to call super!
  4. Using a plugin like phusion's is getting a bit ridiculous. This is ruby, do we really need a plugin just to initialize some default values?
  5. Overriding after_initialize is deprecated as of Rails 3. When I override after_initialize in rails 3.0.3 I get the following warning in the console:

DEPRECATION WARNING: Base#after_initialize has been deprecated, please use Base.after_initialize :method instead. (called from /Users/me/myapp/app/models/my_model:15)

Therefore I'd say write an after_initialize callback, which lets you default attributes in addition to letting you set defaults on associations like so:

  class Person < ActiveRecord::Base
has_one :address
after_initialize :init

def init
self.number ||= 0.0 #will set the default value only if it's nil
self.address ||= build_address #let's you set a default association
end
end

Now you have just one place to look for initialization of your models. I'm using this method until someone comes up with a better one.

Caveats:

  1. For boolean fields do:

    self.bool_field = true if self.bool_field.nil?

    See Paul Russell's comment on this answer for more details

  2. If you're only selecting a subset of columns for a model (ie; using select in a query like Person.select(:firstname, :lastname).all) you will get a MissingAttributeError if your init method accesses a column that hasn't been included in the select clause. You can guard against this case like so:

    self.number ||= 0.0 if self.has_attribute? :number

    and for a boolean column...

    self.bool_field = true if (self.has_attribute? :bool_value) && self.bool_field.nil?

    Also note that the syntax is different prior to Rails 3.2 (see Cliff Darling's comment below)

How can I set some default values to a column in rails?

You have to use model to do it, following is example fo doing. in your migration add following

t.integer "status", default: 1, null: false

Now in your modle app/models/checks.rb put following codes

  STATUS = {
pending: 0,
scheduled: 1,
runnin: 2
}.freeze

enum status: STATUS

Now you can also access like following

check = Check.first
puts check.status

So you are actually saving enum in integer, whose values you define in module. This is one way of doing it.

How can i set the default values of controller parameters?

If you need the last_updated_by param to go within the customer_params (customer hash key for ActionController::Parameters), then:

before_action :set_last_updated_by_param, only: :create

private

def set_last_updated_by_param
params[:customer][:last_updated_by] = params.dig(:customer, :name)
end

The before_action callback adds the new key last_updated_by on the customer params only before the create action is executed.

Notice, no need to modify the customer_params to permit it.


As showed by @JohanWentholt, with_defaults seems to be the best way. Go for it.

Waiting the OP chooses the correct answer.

Set a default value conditionally

From the API docs

after_find and after_initialize callback is triggered for each object that is found and instantiated by a finder, with after_initialize being triggered after new objects are instantiated as well.

You could do something along the lines of:

class Room < ApplicationRecord
after_initialize :set_room_defaults

def set_room_defaults
if people_in_room.size == 1
set room_type = "Single"
elsif people_in_room.size == 2
set room_type = "Double"
elsif people_in_room.size == 3
set room_type = "Triple"
end
end
end

Or you could store the mappings in an Array:

class Room < ApplicationRecord
ROOM_TYPES = %w(Single Double Triple).freeze

after_initialize :set_room_defaults

def set_room_defaults
set room_type = ROOM_TYPES[people_in_room.size - 1]
end
end

set default value of attribute in rails

If you need the value set immediately before the record is created, a before_create event seems more appropriate for your use case.

how to set default value to column in rails while creating migration

You can't do this from the command line - you'll have to edit the migration file and change the corresponding line to something like

add_column :users, :notification_email, :boolean, :default => true

Default values for models in rails

Defining defaults in your migration has some disadvantages as well. This will not work when you just call Model.new.

I prefer to write an after_initialize callback, which lets me set default attributes:

class Model < ActiveRecord::Base
after_initialize :set_defaults, unless: :persisted?
# The set_defaults will only work if the object is new

def set_defaults
self.attribute ||= 'some value'
self.bool_field = true if self.bool_field.nil?
end
end

How to set default values in Rails?

"Correct" is a dangerous word in Ruby. There's usually more than one way to do anything. If you know you'll always want that default value for that column on that table, setting them in a DB migration file is the easiest way:

class SetDefault < ActiveRecord::Migration
def self.up
change_column :people, :last_name, :type, :default => "Doe"
end

def self.down
# You can't currently remove default values in Rails
raise ActiveRecord::IrreversibleMigration, "Can't remove the default"
end
end

Because ActiveRecord autodiscovers your table and column properties, this will cause the same default to be set in any model using it in any standard Rails app.

However, if you only want default values set in specific cases -- say, it's an inherited model that shares a table with some others -- then another elegant way is do it directly in your Rails code when the model object is created:

class GenericPerson < Person
def initialize(attributes=nil)
attr_with_defaults = {:last_name => "Doe"}.merge(attributes)
super(attr_with_defaults)
end
end

Then, when you do a GenericPerson.new(), it'll always trickle the "Doe" attribute up to Person.new() unless you override it with something else.



Related Topics



Leave a reply



Submit