LoginSignup
14
15

More than 5 years have passed since last update.

Rails で serialized Hash なカラムを利用する時あれこれ

Last updated at Posted at 2014-10-25

前提となるカラムサンプル

関連テーブルにしろよというのは置いておいて、以下のようなサンプルを考えます。

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
14
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
15