我如何在ActiveRecord设置默认值?
我看到Pratik的一篇文章,描述了一段丑陋而复杂的代码: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
我在谷歌上看到了以下例子:
def initialize
super
self.status = ACTIVE unless self.status
end
and
def after_initialize
return unless new_record?
self.status = ACTIVE
end
我也见过有人把它放在迁移中,但我更愿意看到它在模型代码中定义。
是否有一个规范的方法来设置默认值的字段在ActiveRecord模型?
这里有一个我用过的解决方案,我有点惊讶还没有加入。
它分为两部分。第一部分是在实际迁移中设置默认值,第二部分是在模型中添加验证,以确保存在为真。
add_column :teams, :new_team_signature, :string, default: 'Welcome to the Team'
您将看到这里已经设置了默认值。现在在验证中,你想要确保字符串总是有一个值,那么就这样做吧
validates :new_team_signature, presence: true
这将为您设置默认值。(对我来说,我有“Welcome to the Team”),然后它将进一步确保该对象始终存在一个值。
希望有帮助!
我遇到了问题after_initialize给出ActiveModel::MissingAttributeError错误时做复杂的发现:
eg:
@bottles = Bottle.includes(:supplier, :substance).where(search).order("suppliers.name ASC").paginate(:page => page_no)
where中的"search"是条件哈希值
所以我用这种方式重写了初始化:
def initialize
super
default_values
end
private
def default_values
self.date_received ||= Date.current
end
super调用是必要的,以确保在执行自定义代码(即:default_values)之前从ActiveRecord::Base正确初始化对象
这里有一个我用过的解决方案,我有点惊讶还没有加入。
它分为两部分。第一部分是在实际迁移中设置默认值,第二部分是在模型中添加验证,以确保存在为真。
add_column :teams, :new_team_signature, :string, default: 'Welcome to the Team'
您将看到这里已经设置了默认值。现在在验证中,你想要确保字符串总是有一个值,那么就这样做吧
validates :new_team_signature, presence: true
这将为您设置默认值。(对我来说,我有“Welcome to the Team”),然后它将进一步确保该对象始终存在一个值。
希望有帮助!
这个问题已经回答了很长时间了,但是我经常需要默认值,并且不喜欢将它们放在数据库中。我创建了一个DefaultValues关注点:
module DefaultValues
extend ActiveSupport::Concern
class_methods do
def defaults(attr, to: nil, on: :initialize)
method_name = "set_default_#{attr}"
send "after_#{on}", method_name.to_sym
define_method(method_name) do
if send(attr)
send(attr)
else
value = to.is_a?(Proc) ? to.call : to
send("#{attr}=", value)
end
end
private method_name
end
end
end
然后像这样在我的模型中使用它:
class Widget < ApplicationRecord
include DefaultValues
defaults :category, to: 'uncategorized'
defaults :token, to: -> { SecureRandom.uuid }
end