データモデルのコールバックをカスタマイズする
Overview
このガイドでは、Mongoid モデルにコールバックを実装して、モデル インスタンスのライフサイクルをカスタマイズする方法を学習できます。
コールバックは、Mongoid がオブジェクトのライフサイクルの指定された時点でトリガーするメソッドです。 オブジェクトの状態が変化する前または後に、指定されたアクションを開始できます。
Mongoid は ActiveRecord のコールバックの多くを実装します。 詳しくは、Active レコードのドキュメントの「 コールバック 」を参照してください。
サポートされているコールバック
Mongoid は、 ドキュメント モジュールを実装するモデル クラスに対して次のコールバックをサポートしています。
after_initialize
after_build
before_validation
after_validation
before_create
around_create
after_create
after_find
before_update
around_update
after_update
before_upsert
around_upsert
after_upsert
before_save
around_save
after_save
before_destroy
around_destroy
after_destroy
前述のコールバックの型の詳細については、Rails APIドキュメントの ActiveRecord::コールバック参照を参照してください。
最上位ドキュメントモデルと埋め込みドキュメントモデルの両方でコールバックを実装できます。
注意
コールバック呼び出しの動作
効率の場合、Mongoid は永続化アクションを実行したドキュメントに対してのみコールバックを呼び出します。 この動作により、Mongoid は大規模な階層をサポートし、ドキュメント階層全体でコールバックを呼び出さないことで、最適化されたアトミックな更新を効率的に処理できます。
ドメイン ロジックのコールバックを実装するときは注意してテスト可能性を確保します。これらの設計ではチェーン内のコールバックが実行を停止したときに予期しないエラーにつながる可能性があるためです。 バックグラウンド ジョブのキューアップなど、プログラムの主要機能外の横断的な問題にはコールバックを使用することをお勧めします。
ドキュメント コールバック
モデル クラスにコールバックを実装して登録する必要があります。 コールバックを登録するには、通常のメソッド、ブロック、Proc
オブジェクトを使用するか、クラスまたはモジュールを使用するカスタムコールバックオブジェクトを定義します。
この例では、次の方法で Contact
モデルクラスのコールバックを登録する方法を示します。
Contact
インスタンスがMongoDBに保存される前にprocess_phone
メソッドをトリガーするbefore_save
クラスメソッドが含まれます。process_phone
メソッドはクラスで個別に定義されます。after_destroy
クラスメソッドを含み、Contact
インスタンスが削除されたときにブロックを使用してメッセージを出力します。
class Contact include Mongoid::Document field :name, type: String field :phone, type: String # Creates a callback to clean phone numbers before saving before_save :process_phone protected def process_phone self.phone = phone.gsub(/[^0-9]/, "") if attribute_present?("phone") end # Creates a callback to send a message about object deletion after_destroy do p "deleted the contact for #{name}" end end
次のコードは、コールバックアクションを示すデータ操作を実行します。
Contact.create(name: 'Serena Atherton', phone: '999 555-3030') # => `phone` field saved as '9995553030' Contact.create(name: 'Zayba Haq', phone: '999 123?5050') # => `phone` field saved as '9991235050' Contact.first.destroy # => Console message: "deleted the contact for Serena Atherton"
コールバック機能は Active サポートから取得されているため、コールバックを登録するには代わりに set_callback
クラスメソッド構文を使用できます。 次のコードは、この構文を使用して、aliases
配列の name
フィールドの元の値を保存するコールバックを作成する方法を示しています。
class Contact include Mongoid::Document field :name, type: String field :phone, type: String field :aliases, type: Array, default: [] set_callback(:update, :before) do |document| if document.name_changed? document.push(aliases: document.name_was) end end end Contact.create(name: 'Xavier Bloom', phone: '4447779999') Contact.first.update(name: 'Xav - coworker') # Saved document in MongoDB: # {"aliases":["Xavier Bloom"],"name":"Xav - coworker","phone":"4447779999"}
関連付けコールバック
Mongoid は、次の関連付けコールバックを提供します。
after_add
after_remove
before_add
before_remove
モデルクラスに関連付けコールバックを登録すると、次の関連付けのいずれかからドキュメントを追加または削除するたびに呼び出されます。
embeds_many
has_many
has_and_belongs_to_many
それぞれの関連付けのオプションとして関連付けコールバックを指定します。 追加または削除されたドキュメントを、指定されたコールバックのパラメーターとして渡す必要があります。
次のコードは、複数の SavedArticle
インスタンスを埋め込む User
モデルクラスに関連付けコールバックを登録して、1 つのインスタンスの埋め込みドキュメント数を制限する方法を示しています。
class User include Mongoid::Document field :username, type: String # Registers the callback in the association statement embeds_many :saved_articles, before_add: :send_message protected # Passes the association document as a parameter to the callback def send_message(saved_article) if saved_articles.count >= 10 p "you can't save more than 10 articles at a time" throw(:abort) end end end class SavedArticle include Mongoid::Document embedded_in :user field :url, type: String end
スレッド ローカル変数
cascade_callbacks: true
が設定された関連付けに子ドキュメントを埋め込んでいる場合、埋め込まれた子コールバックはRuby フィルター 内で実行されます。つまり、Thread#[]
メソッドと Thread#[]=
メソッドを使用してフィルター ローカル変数を取得および設定している場合、それらのコールバックは期待される値の読み取りや設定を行いません。
Thread#thread_variable_get
Thread#thread_variable_set
true スレッド ローカル変数を取得して設定するには、9.0.3 メソッドと メソッドを使用することをお勧めします。便宜上、Mongoid v では、この機能を実装するために Mongoid::Threaded.get メソッドと Mongoid:Threaded.set メソッドが導入されています。
詳細情報
Mongoid がコールバックを実行中ないようにする方法については、Active レコード ドキュメントの次の参照を参照してください。
Mongoid がトランザクションでコールバックを管理する方法の詳細については、「 トランザクションとセッション のガイド 」を参照してください。