- 更新日: 2014年5月8日
- Rails
Rails4でserializeしてデータをDBに保存させる
Rails で配列やハッシュなどコレクション的なデータを、データベースにシリアライズして保存しておく方法。find で読み出すと元のオブジェクトの形式で読み出してくれるので超便利です。
— 環境 —
rails 4.0.1
マイグレーション
マイグレーションファイルでは、serialize して保存するフィールドのデータ型に text を指定しておきます。tags をシリアライズ。
db/migrate/***_create_post.rb
1 2 3 4 5 6 7 8 9 10 |
class CreatePost < ActiveRecord::Migration def change create_table :post do |t| t.string :content t.text :tags # => array of tag t.timestamps end end end |
モデルで serialize する属性を指定
モデルで ActiveRecord の serialize メソッドに対象の属性を指定するだけ。ここでは、tags をシリアライズする。
app/models/post.rb
1 2 3 |
class Post < ActiveRecord::Base serialize :tags end |
あとは普通に create や save で保存でき、find などで取得すると元のオブジェクトの形で取得できます。以下 pry で試しました。
1 2 3 4 5 6 7 8 |
pry(main)> post = Post.new pry(main)> post.content = "パソコン買った" pry(main)> post.tags = ["diary", "pc"] pry(main)> post.save pry(main)> Post.find(1).tags ["diary", "pc"] |
直接 MySQL を覗くと分かりますが、シリアライズされたデータは DB には yaml 形式の文字列で保存されています。ActiveRecord のメソッド find などで取得すると元のオブジェクトの形式で取得できます。素晴らしい。
ArgumentError: undefined class/module への対処
独自に定義したクラスのインスタンスを含む配列やハッシュなどを serialize して保存した場合、find の際に以下のようにクラス名/モジュール名を見つけられないエラーが出る時がありました。
1 2 3 |
ArgumentError: undefined class/module |
少々これではまりましたが、これは DB から deserialize する際に、Rails の autoload の機能が呼ばれないためらしい…。あまり自信ないですが、英語圏ブログでそのような情報がいくつか見つけた。
なので、deserialize に必要なクラスが定義されているファイルを、事前に明示的に require しておくと無事に deserialize できます。
1 2 3 4 5 6 7 8 9 10 |
pry(main)> SomeModel.find(1).some_attributes ArgumentError: undefined class/module **** pry(main)> require "some_attributes_file" => true pry(main)> SomeModel.find(1).some_attributes => [#<SomeAttribute:0x007f86e1e7a350 ..., ...>] |
serialize 便利です。
- Rails の関連記事
- RailsでMySQLパーティショニングのマイグレーション
- Rails ActiveRecordでdatetime型カラムのGROUP BY集計にタイムゾーンを考慮する
- RailsプラグインGemの作成方法、RSpecテストまで含めたrails pluginの作り方
- RailsでAMPに対応するgemをリリースしました
- Railsでrequest.urlとrequest.original_urlの違い
- Railsでwheneverによるcronバッチ処理
- Google AnalyticsのRails Turbolinks対応
- Railsアプリにソーシャル・シェアボタンを簡単設置
- Rails監視ツール用にErrbitをHerokuで運用
- Facebook APIバージョンのアップグレード手順(Rails OmniAuth)
Leave Your Message!