ActiveRecord ::存储默认值

时间:2012-03-12 03:32:21

标签: ruby-on-rails activerecord store

使用新的ActiveRecord :: Store进行序列化,the docs给出了以下示例实现:

class User < ActiveRecord::Base
  store :settings, accessors: [ :color, :homepage ]
end

是否可以使用默认值声明属性,类似于:

store :settings, accessors: { color: 'blue', homepage: 'rubyonrails.org' }

5 个答案:

答案 0 :(得分:17)

不,没有办法在store通话中提供默认值。 store macro非常简单:

def store(store_attribute, options = {})
  serialize store_attribute, Hash
  store_accessor(store_attribute, options[:accessors]) if options.has_key? :accessors
end

并且所有store_accessor都会遍历:accessors并为每个创建accessor和mutator方法。如果您尝试使用带有:accessors的哈希值,您最终会向store添加一些您不想要的内容。

如果您想提供默认值,那么您可以使用after_initialize挂钩:

class User < ActiveRecord::Base
  store :settings, accessors: [ :color, :homepage ]
  after_initialize :initialize_defaults, :if => :new_record?
private
  def initialize_defaults
    self.color    = 'blue'            unless(color_changed?)
    self.homepage = 'rubyonrails.org' unless(homepage_changed?)
  end
end

答案 1 :(得分:2)

我也想解决这个问题并最终为Storext做出贡献:

class Book < ActiveRecord::Base
  include Storext.model

  # You can define attributes on the :data hstore column like this:
  store_attributes :data do
    author String
    title String, default: "Great Voyage"
    available Boolean, default: true
    copies Integer, default: 0
  end
end

答案 2 :(得分:1)

尝试使用https://github.com/byroot/activerecord-typedstore gem。它允许您设置默认值,使用验证结束其他。

答案 3 :(得分:0)

这是我刚刚一起解决这个问题的原因:

# migration
  def change
    add_column :my_objects, :settings, :text
  end

# app/models/concerns/settings_accessors_with_defaults.rb
module SettingsAccessorsWithDefaults
  extend ActiveSupport::Concern

  included do
    serialize :settings, Hash
    cattr_reader :default_settings
  end

  def settings
    self.class.default_settings.merge(self[:settings])
  end

  def restore_setting_to_default(key)
    self[:settings].delete key
  end

  module ClassMethods
    def load_default_settings(accessors_and_values)
      self.class_variable_set '@@default_settings', accessors_and_values

      self.default_settings.keys.each do |key|
        define_method("#{key}=") do |value|
          self[:settings][key.to_sym] = value
        end

        define_method(key) do
          self.settings[key.to_sym]
        end
      end
    end
  end
end

# app/models/my_object.rb
  include SettingsAccessorsWithDefaults
  load_default_settings(
    attribute_1: 'default_value',
    attribute_2: 'default_value_2'
  )
  validates :attribute_1, presence: true


irb(main):004:0> MyObject.default_settings
=> {:attribute_1=>'default_value', :attribute_2=>'default_value_2'}
irb(main):005:0> m = MyObject.last
=> #<MyObject ..., settings: {}>
irb(main):005:0> m.settings
=> {:attribute_1=>'default_value', :attribute_2=>'default_value_2'}
irb(main):007:0> m.attribute_1 = 'foo'
=> "foo"
irb(main):008:0> m.settings
=> {:attribute_1=>"foo", :attribute_2=>'default_value_2'}
irb(main):009:0> m
=> #<MyObject ..., settings: {:attribute_1=>"foo"}>

答案 4 :(得分:0)

以下代码的优点是不会在每个用户记录上保存默认值,从而减少了数据库存储使用量,并且在您要更改默认值时很容易

{{1}}