我如何在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模型?
这个问题已经回答了很长时间了,但是我经常需要默认值,并且不喜欢将它们放在数据库中。我创建了一个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
我也看到人们在迁徙中使用这种方法,但我更愿意看到
在模型代码中定义。
是否有一个规范的方法来设置字段的默认值
ActiveRecord模型?
在Rails 5之前,规范的Rails方法实际上是在迁移中设置它,只需要在db/schema中查找即可。rb每当想要看到什么默认值是由DB为任何模型设置。
与@Jeff Perrin的回答相反(这有点老),在使用Model时,迁移方法甚至会应用默认值。新的,由于一些Rails魔法。在Rails 4.1.16中验证。
最简单的东西往往是最好的。较少的知识负债和代码库中的潜在混淆点。而且它‘just works’。
class AddStatusToItem < ActiveRecord::Migration
def change
add_column :items, :scheduler_type, :string, { null: false, default: "hotseat" }
end
end
或者,在不创建新列的情况下更改列,然后执行以下操作:
class AddStatusToItem < ActiveRecord::Migration
def change
change_column_default :items, :scheduler_type, "hotseat"
end
end
或者更好:
class AddStatusToItem < ActiveRecord::Migration
def change
change_column :items, :scheduler_type, :string, default: "hotseat"
end
end
查看官方RoR指南以获得列更改方法中的选项。
null: false禁止在DB中使用null值,而且,作为一个额外的好处,它还会进行更新,以便所有先前为null的DB记录也会使用该字段的默认值设置。如果您愿意,您可以在迁移中排除这个参数,但我发现它非常方便!
Rails 5+的规范方式是,正如@Lucas Caton所说:
class Item < ActiveRecord::Base
attribute :scheduler_type, :string, default: 'hotseat'
end
这个问题已经回答了很长时间了,但是我经常需要默认值,并且不喜欢将它们放在数据库中。我创建了一个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