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?
}