elasticsearchの返却値にincludesを通常のやりかたでかませるとエラーがでる。
bulletでN+1の警告が拾われないため、つい見逃しやすい。
備忘録的なメモ。
前提
elasticsearch_railsにはkaminariモジュールがあるため、
elasticsearchの返却値に下記のようにpageを加えてあげることで、
ページングを実現できる
app/controllers/sample_models_controller.rb
class SampleModelsController < ApplicationController
def index
@sample_models = SampleModel.__elasticsearch__.search({query_json}).page(params[:page]).records
end
end
viewは下記のようにElasticSearchを意識することなく
ActiveRecordと同様、kaminariの一般的な実装方法で記述できる。
これによりページング機能が実現できる。
これはElasticSearch内にkaminariモジュールがあるため、それによって実現されている
app/views/sample_models/index.html.haml
- @sample_models.each do |sample_model|
= sample_model.title
= paginate @sample_models
問題: .includesをつけようとすると..
だが、ActiveRecordライクに下記のようにしてしまうと、
app/controllers/sample_models_controller.rb
# NG例
class ModelsController < ApplicationController
def index
SampleModel.__elasticsearch__.search({query_json}).page(params[:page]).records.includes(:child_model)
end
end
kaminariで下記のエラーが発生する
undefined method `total_pages' for #<SampleModel::ActiveRecord_Relation:0x00************>
.includes(:child_model)
と記述してしまった時点で、
Elasticsearch::Model::Response::Records
が、SampleModel::ActiveRecord_Relation
に変換されてしまい、ElasticSearchのkaminariモジュールに用意されたパラメータがそぎ落ちてしまうことが原因
解決策
elasticsearch_railsのrecordにoptionでincludesを引き渡せるようになっているので、
それを利用すればよい。
sample_models_controller.rb
# OK例
class SampleModelsController < ApplicationController
def index
SampleModel.__elasticsearch__.search({query_json}).page(params[:page]).records(includes: :child_model)
end
end