Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
5
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

@razokulover

searchkickで多対多のデータを同期的にインデックスさせる

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

これでうまくいく。

【参考】

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
5
Help us understand the problem. What are the problem?