我如何在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模型?


当前回答

在rails 3中使用default_scope

接口文档

ActiveRecord模糊了在数据库(模式)中定义的默认值和在应用程序(模型)中完成的默认值之间的区别。在初始化过程中,它解析数据库模式并记录其中指定的任何默认值。稍后,在创建对象时,它将分配那些模式指定的默认值,而不涉及数据库。

讨论

其他回答

一个比建议的答案更好/更干净的潜在方法是覆盖访问器,像这样:

def status
  self['status'] || ACTIVE
end

请参阅ActiveRecord::Base文档中的“覆盖默认访问器”和StackOverflow中关于使用self的更多信息。

伙计们,我最后做了以下事情:

def after_initialize 
 self.extras||={}
 self.other_stuff||="This stuff"
end

效果好极了!

类似的问题,但背景略有不同: -如何为Rails activerecord的模型中的属性创建默认值?

最佳回答:这取决于你想要什么!

如果你想让每个对象都以一个值开始:使用after_initialize:init

您希望new.html表单在打开页面时具有默认值?使用https://stackoverflow.com/a/5127684/1536309

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 

如果你想让每个对象都有一个从用户输入中计算出来的值:使用before_save:default_values 你想让用户输入X然后Y = X+'foo'?使用:

class Task < ActiveRecord::Base
  before_save :default_values
  def default_values
    self.status ||= 'P'
  end
end

我已经用了一段时间了。

# post.rb
class Post < ApplicationRecord
  attribute :country, :string, default: 'ID'
end

After_initialize方法已弃用,请改用回调方法。

after_initialize :defaults

def defaults
  self.extras||={}
  self.other_stuff||="This stuff"
end

然而,在迁移中使用:default仍然是最干净的方式。