0

我很好奇开发一个为新的 ActiveRecord 记录设置默认值的方案是否可行。根据这里的一些答案和这篇关于设置属性的帖子,我想出了这样的东西:

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

对于偏执狂,该常量还可用于在迁移中设置默认值:

class CreateTacos  < ActiveRecord::Migration

  def defaults
    Taco::DEFAULT_ATTR
  end 

  def change
    add_column :tacos, :spice_level, :integer, :default => defaults[:spice_level]
  end 
end

什么可能有用(直到有人指出我忽略的一些明显方面!)如果这个方案作为回调内置到 ActiveRecord 中,ala before_save(类似于“new_record_defaults”)。您可以重写该方法并返回符号 => 默认对的哈希值,甚至可能偏执的迁移代码也可以利用这一点。

我对 Rails 还很陌生,所以我准备好被告知一个计划已经存在或者为什么这是一个愚蠢的想法,但欢迎反馈。:)

更新:根据 Anton Grigoriev 的回答,我认为属性默认宝石是要走的路。对于后代,这里是一个额外的关注,基于作者的原始,用于访问创建的默认值:

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
4

2 回答 2

1

您可以使用此 gem https://github.com/bsm/attribute-defaults来设置属性默认值

于 2013-04-30T17:03:16.467 回答
0

我更愿意将此逻辑保留在应用程序级别而不是数据库级别(通过迁移)。

在应用程序级别,这只是属性的覆盖

class Taco < ActiveRecord::Base
  def spice_level
    read_attribute(:spice_level) || 4
  end
end

基本情况是,如果您将此属性设置为 5,则为 5。如果没有,则为 4。

关于覆盖属性的参考:http: //api.rubyonrails.org/classes/ActiveRecord/Base.html#label-Overwriting+default+accessors

于 2013-04-30T17:06:26.837 回答