ActiveRecord:: Сохранить со значениями по умолчанию
Используя новый метод ActiveRecord:: Store для сериализации, документы дают следующую реализацию примера:
class User < ActiveRecord::Base
store :settings, accessors: [ :color, :homepage ]
end
Можно ли объявлять атрибуты со значениями по умолчанию, что-то вроде:
store :settings, accessors: { color: 'blue', homepage: 'rubyonrails.org' }
?
Ответы
Ответ 1
Нет, нет способа указать значения по умолчанию внутри вызова store
. Макрос store
довольно прост:
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
, который вы не хотели.
Если вы хотите указать значения по умолчанию, вы можете использовать hook 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
Ответ 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
Ответ 3
Вот что я только что взломал, чтобы решить эту проблему:
# 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
попробуйте использовать https://github.com/byroot/activerecord-typedstore gem. Он позволяет установить значение по умолчанию, использовать другой конец проверки.