LoginSignup
125
118

More than 5 years have passed since last update.

Rails4 DB連携なしモデルでバリデーション機能を使う

Last updated at Posted at 2014-03-04

Goal

  • RailsでActiveRecord機能モデルを使うときは、必ずバックエンドでDBと紐付いていなければならない
  • 今回は、たとえばCSVファイルのCRUDなどRails4でDB連携しないモデルを作成したい
  • RailsのActiveModelが搭載するvalidation機能・callback機能を使って、モデル呼び出し側が意識することなく自動でオブジェクトをチェックするエコシステムをつくりたい

Milestone

  • rails generate modelを実行するとDBと関連付けられてしまうため、これは使わない
    • ActiveRecordを継承したモデルが作成されてしまう、migrationファイルが作成されてしまう
  • モデルクラスを新規作成し、クラスにActiveModelモジュールをMixInさせることで、必要な機能だけをクラスに取り込むことができる(Rails3とRails4ではやりかたがけっこう違うらしい)
  • include ActiveModel::Modelによってvalidationが使えるようになる
  • (追記) ActiveModel::ModelをincludeしていればCallbacksはincludeしなくてもOKでした
    • // include ActiveModel::Callbacksによってコールバックが使えるようになる

Example

  • フォームを使ってアップロードされてきたcsvファイルをそのままサーバに保存するケース
app/models/csv.rb
class Csv
  include ActiveModel::Model
  #include ActiveModel::Callbacks

  attr_accessor :operator_id, :type, :data_csv
  define_model_callbacks :save

  before_save {
    self.valid?
  }

  validates :file_path, presence: true
  validates :type, presence: true, numericality: true
  validates :data_csv, presence: true

  def save
    run_callbacks :save do
      @uploaded_file_str = self.data_csv.read
      File.open(self.file_path, 'wb') do | new_file |
        new_file.write(@uploaded_file_str)
      end
    end
  end
end

ベーシックなクラスに機能をMixIn

class Csv
  include ActiveModel::Model
  #include ActiveModel::Callbacks
  • include ActiveModel::Modelによってvalidatesメソッドなどが有効に // include ActiveModel::Callbacksによってコールバック機能が有効になる
  • ActiveRecord継承のモデルでない場合、validatesメソッドに'on'を渡しても作動せず、またbefore_saveなどのメソッドがデフォルトで使えないので、コールバックを明示的に指定する
  • モデル呼び出し側で、model.valid?のようにバリデーションを実行したいだけならばコールバック機能を使う必要はない

コールバックを使ってValidation自動実行をつくる

Csvモデルに定義されたsaveメソッドにコールバックを設定する
define_model_callbacks定義をいれることで、デフォルトでは、before_save, around_save, after_saveが有効になる

define_model_callbacks :save

さらに、before_saveなどのイベントを発火させるためにsaveメソッドをrun_callbacksでラップする

def save
  run_callbacks :save do
    # save時に実行させたい実装
  end
end

before_saveなどのタイミングで実行させたいロジックを実装する
ブロックでなくてもメソッドを指定してもいい

before_save {
  self.valid?
}

References

125
118
1

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
125
118