前提となるカラムサンプル
関連テーブルにしろよというのは置いておいて、以下のようなサンプルを考えます。
class User < ActiveRecord::Base
serialize :usable_features, Hash # 利用可能な機能みたいなイメージ
end
例えば {analytics: 'active_users', ip_address_control: true}
のような感じで、複数の機能に関する設定を持つような感じ。analytics
に関してはいろんな値を持てるような。
migration でのデフォルト値指定
参考: Rails serialization with default value and new objects - stackoverflow
参考のまんまですが、default に Hash を私 #to_yaml
します。serialized Hash した場合には Yaml 形式で保存されるので、そのままと言えばそのままですね。
add_column :user, :usable_features, :text, default: {analytics: 'active_users'}.to_yaml
API としてモデル更新を受ける場合
strong_parameters の設定に一曲あります。ネストしたモデルの更新に近い感じです。
# Hash の key となるものを並べる
params.require(:user).permit(usable_features: ['analytics', 'ip_address_control'])
form からのモデル更新を受ける場合
参考: How to edit Rails serialized hashes in a form? - stackoverflow
参考サイトにはいくつかの手法が提案されているが、Hash の key 分のアクセサメソッドを定義するのが分かりやすい気がします。
class User < ActiveRecord::Base
def analytics_usable_feature
usable_features[:analytics]
end
def analytics_usable_feature=(value)
if value.present?
usable_features[:analytics] = value
else
usable_features.delete(:analytics)
end
end
# 他の key の分も作る
end
上記は一例なので、method_missing
を使ったり、define_method
を使ったりして key 分のメソッド生成をもう少しスッキリ書けるようにしてもいいかもしれないです。以下のようにしているケースもありました。
各 Hash の key でアクセサを作っておけば view
の方は普通の form の書き方ができます。
f.radio_button :analytics_usable_feature, 'active_users'
f.label :analytics_usable_feature, 'active_users', value: 'active_users'
strong_parameters も追加する必要がありますね。
factory_girl の設定
参考: Add a Serialized Hash Attribute to a Factory_Girl Definition - RUBY COLORED GLASSES
lazy attributes で指定します。または参考にあるように、単一の値が引数になるように書き換えます。
factory :user do
usable_features { {analytics: 'active_users'} }
end