2012-03-12 1 views

答えて

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を反復処理し、それぞれのためのアクセサとミューテータメソッドを作成することです。 :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

+1、@mu通常このシナリオでは、 'set if not set'イディオムを使用します。つまり' self.color || = 'blue'; self.homepage || = 'rubyonrails.org' '。これは 'dirty'チェックを避けます。 –

+1

@KandadaBoggu:' || = 'への唯一の欠点はブール値の属性を持つ場合です。 Perlの '// ='のように "定義されていなければセットされていない"というのは残念です。 –

+0

ええ、それは本当ですが、 '|| ='イディオムを使うとブーリアンを違う方法で扱わなければなりません。 –

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"}> 
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 
関連する問題