ElasticseachをRubyから扱えるようになるsearchkickというgemがある。
このgemには、例えばUserというモデルにデータが追加されるとそれと同時にElasticsearch側にそのインデックスを作ってくれる便利機能がある。
また、Userを親に持つAddressという子モデルがある場合も以下のように書くとUserに紐づくAddressが新規に追加されたとき同時にインデックスを作成してくれる。
class Address < ActiveRecord::Base
belongs_to :user
after_commit :reindex_user
def reindex_user
user.reindex
end
end
1対1や多対1のような関連の時にはこのやり方でいいのだけど、多対多のときは少し工夫が必要になる。
例えば、
(親)Article
(中間)ArticleTagging
(親)Tag
のような多対多の構成の関連があったとき、Articleに紐づくTagが追加されたときにそのTagをインデックスしたいとする。
公式のやり方に則ると下記のようになるけれども、
class Tag < ActiveRecord::Base
has_many :article_taggings
has_many :articles, through: :article_taggings
after_commit :reindex_article
def reindex_article
article.reindex
end
end
これだとうまくいかない。
多対多でもうまく同期的にインデックスさせるためには、下記のように中間モデルに記述する。
class ArticleTagging < ActiveRecord::Base
belongs_to :tag
belongs_to :article
after_commit :reindex # after_saveだとFactoryGirlを使っているときにコケる
def reindex
article.reload.reindex
end
end
これでうまくいく。
【参考】