Rails – テーブルなしのモデルを利用する方法

RailsではモデルとDBのテーブルが1対1の関係になっていることが多いですが、対応するテーブルはないけどモデルを利用したい、というシーンがあると思います。

特に画面の入力内容が1つのテーブルに対応していない場合によく使われるとおもいます。例えば、CSVファイルの内容をインポートして各テーブルにデータを登録する場合のファイルアップロード画面用でテーブルなしモデルを使うと便利です。

このメモではこの「テーブルなしモデル」する方法を紹介します。

 

なぜ「テーブルなしモデル」を使うか

テーブルなしモデルを利用することで以下の3つのメリットが得られると思います。

  1. ActiveModelの強力なバリデーション機能を使える
    ⇒ 自分でバリデーションロジックを書かなくて済みます
  2. 他のソースコードとの統一性が保てる
    ⇒ 入力をモデル化することでform_forなどのメソッドが使えるため、テーブルありの場合のロジックと同様に処理することができます
  3. ソースコードが汚くならない
    ⇒ 無理にテーブルなしモデルを使わないで実装しようすると、既存のテーブルありモデルのソースに多くのロジックが追加され、何がしたいソースなのかわけけがわからなくなってしまいます

 

テーブルなしモデルの実装

ActiveAttr」というgemを利用すると「テーブルなしモデル」が少ない記述量で実現できます。このgemを利用しなくてもテーブルなしモデルは実現できますが、コードの可読性も高まるので利用することをオススメします。

ActiveAttrのインストールはGemfileに以下のように記述してbundle installコマンドを実行します。

gem 'active_attr'

 

このgemがインストールされていると以下のようにテーブルなしモデルを記述できます。

class Someone
  include ActiveAttr::Model

  attribute :name
  attribute :age

  validates :name, :presence => true

 end

ポイントはActiveAttr::Modelをインクルードしている点と、attributeというキーワードでカラムを定義している点です。以上でテーブルなしモデルが実現できました。

ただし、注意点があります。通常のテーブルありモデルはActiveRecordを基底クラスとしたクラスですが、ActiveAttrではActiveModelクラスを利用しています。そのため、テーブルありモデルでは使えたメソッドがテーブルなしモデルでは使えない場合もあります。(そんなにないですが)

また、モデルの属性名やバリデーションメッセージのja.ymlにおける記述場所も以下のようにActiveRecordとActiveModelでは異なっているため、注意が必要です。

ja:
 activemodel:
    attributes:
      someone:
        name: 名前
        age: 年齢
    errors:
      models:
        inventory_import:
          attributes:
            csv_file:
              blank: が入力されていません
  activerecord:
    attributes:
      item:
        name: 商品名
    errors:
      models:
        item:
          attributes:
            name:
              blank: が入力されていません

 

環境

Rails 3.2.9

参考文献

#326 ActiveAttr

 

 

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です