Rails:如何在ActiveRecord中设置默认值?

45 浏览
0 Comments

Rails:如何在ActiveRecord中设置默认值?

如何在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

  def after_initialize 
    return unless new_record?
    self.status = ACTIVE
  end

我也看到有人把它放到迁移中,但我宁愿在模型代码中定义它。

有没有一种规范的方式来为ActiveRecord模型中的字段设置默认值?

admin 更改状态以发布 2023年5月21日
0
0 Comments

Rails 5+

在你的模型中,可以使用attribute方法,例如:

class Account < ApplicationRecord
  attribute :locale, :string, default: 'en'
end


你也可以把一个lambda传递给default参数,例如:

attribute :uuid, :string, default: -> { SecureRandom.uuid }

第二个参数是类型,也可以是自定义类型类的实例,例如:

attribute :uuid, UuidType.new, default: -> { SecureRandom.uuid }

0
0 Comments

每种可用的方法都存在一些问题,但我相信定义一个after_initialize回调是最好的方法,理由如下:

  1. default_scope将为新模型初始化值,但然后它将成为您查找模型的范围。如果您只想将某些数字初始化为0,那么这不是您想要的。
  2. 在迁移中定义默认值有时也有效...正如已经提到的,当你只是调用Model.new时,这种方法是行不通的。
  3. 重写initialize可以起作用,但不要忘记调用super
  4. 使用像Phusion这样的插件有点荒谬。这是Ruby,我们真的需要一个插件来初始化一些默认值吗?
  5. 自Rails 3之后,弃用了重写after_initialize。当我在Rails 3.0.3中重写after_initialize时,控制台会提示以下警告:

DEPRECATION WARNING: Base#after_initialize已被弃用,请使用Base.after_initialize:方法。 (来自/Users/me/myapp/app/models/my_model:15)

因此,我建议编写一个after_initialize回调函数,它使您能够在关联上设置默认值的同时,也可以为属性设置默认值,如下所示:

  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    

现在,您只需要查找一个地方就可以初始化您的模型。在有更好的方法出现之前,我一直使用这种方法。

警告:

  1. 对于布尔字段,请这样做:

    self.bool_field = true if self.bool_field.nil?

    请参阅保罗·拉塞尔(Paul Russell)对此回答的评论以获取更多详细信息。

  2. 如果您只为一个模型选择了子集列(即,在查询中使用select,例如Person.select(:firstname,:lastname).all),如果您的init方法访问没有包含在select关键字中的列,您将获得 MissingAttributeError。您可以这样针对此情况进行保护:

    self.number ||= 0.0 if self.has_attribute? :number

    对于布尔列,可以这样:

    self.bool_field = true if (self.has_attribute? :bool_value) && self.bool_field.nil?

    还要注意,在Rails 3.2之前,语法是不同的(请参阅下面Cliff Darling的评论)

0