How can I set default value in ActiveRecord?
I see a post from Pratik that describes an ugly, complicated chunk of code: http://m.onkey.org/2007/7/24/how-to-set-default-values-in-your-model
class Item < ActiveRecord::Base
def initialize_with_defaults(attrs = nil, &block)
initialize_without_defaults(attrs) do
setter = lambda { |key, value| self.send("#{key.to_s}=", value) unless
!attrs.nil? && attrs.keys.map(&:to_s).include?(key.to_s) }
setter.call('scheduler_type', 'hotseat')
yield self if block_given?
end
end
alias_method_chain :initialize, :defaults
end
I have seen the following examples googling around:
def initialize
super
self.status = ACTIVE unless self.status
end
and
def after_initialize
return unless new_record?
self.status = ACTIVE
end
I've also seen people put it in their migration, but I'd rather see it defined in the model code.
Is there a canonical way to set default value for fields in ActiveRecord model?
after_initialize method is deprecated, use the callback instead.
however, using :default in your migrations is still the cleanest way.
I've found that using a validation method provides a lot of control over setting defaults. You can even set defaults (or fail validation) for updates. You even set a different default value for inserts vs updates if you really wanted to. Note that the default won't be set until #valid? is called.
Regarding defining an after_initialize method, there could be performance issues because after_initialize is also called by each object returned by :find : http://guides.rubyonrails.org/active_record_validations_callbacks.html#after_initialize-and-after_find
This is what constructors are for! Override the model'sinitialize
method.Use the
after_initialize
method.I ran into problems with
after_initialize
givingActiveModel::MissingAttributeError
errors when doing complex finds:eg:
"search" in the
.where
is hash of conditionsSo I ended up doing it by overriding initialize in this way:
The
super
call is necessary to make sure the object initializing correctly fromActiveRecord::Base
before doing my customize code, ie: default_valuesAlthough doing that for setting default values is confusing and awkward in most cases, you can use
:default_scope
as well. Check out squil's comment here.