Reputation: 718
I'm curious as to whether it's feasible to develop a scheme for setting the default values for new ActiveRecord records. Based on some of the answers here, and this post on setting attributes, I've come up with something like this:
class Taco < ActiveRecord::Base
DEFAULT_ATTR = {spice_level: 4}
before_save do |taco|
if new_record?
DEFAULT_ATTR.each do |k,v|
taco[k] ||= v
end
end
end
end
For the paranoid, the constant could be used to also set the default in the migration:
class CreateTacos < ActiveRecord::Migration
def defaults
Taco::DEFAULT_ATTR
end
def change
add_column :tacos, :spice_level, :integer, :default => defaults[:spice_level]
end
end
What could be useful (until someone points out some obvious aspect I've overlooked!) is if this scheme was built into ActiveRecord as a callback, ala before_save (something like "new_record_defaults"). You could override the method and return a hash of symbol => default pairs, and maybe even the paranoid migration code could also leverage this.
I'm still fairly new to Rails, so I'm prepared to be told a scheme already exists or why this is a dumb idea, but feedback is welcome. :)
Update: Per Anton Grigoriev's answer, I think the attribute-defaults gem is the way to go. For posterity, here is an additional Concern, based on the author's original, for getting access to the defaults created:
module ActiveRecord
module AttributesWithDefaultsAccessor
extend ActiveSupport::Concern
def all_defaults
defaults = {}
self.private_methods.each do |method|
if method =~ /^__eval_attr_default_for_(.+)$/
defaults[$1.to_sym] = self.send(method)
end
end
defaults
end
end
class Base
include AttributesWithDefaultsAccessor
end
end
Upvotes: 0
Views: 538
Reputation: 24815
I would prefer to keep this logic in application level instead of database level(by migration).
In application level, this is simply an overwriting of attribute
class Taco < ActiveRecord::Base
def spice_level
read_attribute(:spice_level) || 4
end
end
The basic is, if you have set this attribute to something say 5, it is 5. If not, it is 4.
Ref about overwriting attribute: http://api.rubyonrails.org/classes/ActiveRecord/Base.html#label-Overwriting+default+accessors
Upvotes: 0
Reputation: 1219
You could use this gem https://github.com/bsm/attribute-defaults for setting attribute default values
Upvotes: 1