acts-as-taggable-onとRansackを使用したタグの複合検索
やりたいこと
表題の通り“acts-as-taggable-onとRansackを使用したタグの複合検索”
複合検索とは、スペース区切りのAND検索を指します。
今回は、映像コンテンツにtypeというタグを付けて管理するという例で考えてみましょう。
同じようなことをする方は、少ないと思われますが、検索しても意外と結果が出てこないので、今後の方のために。
複合検索したいという場合は、modelの実装をすっ飛ばして実装すれば問題なく実装できるはず。
すこしRESTfulでないPathですが、ご勘弁ください。
最終実装
app/models/Video.rb
class Video < ActiveRecord::Base
acts_as_taggable_on :type
end
app/controller/searches.rb
class SearchesController < ApplicationController
def video
groupings = [] # 空配列生成
# パラメーターがあれば分割し、複数のAND条件分を生成する
if params[:q].present?
keywords = params[:q][:type_name_cont].split(/[\p{blank}\s]+/)
keywords.each { |value| groupings.push(type_name_cont: value) }
end
# 生成したAND条件を検索する。初期の場合、全件出力
@query = Video.ransack(
combinator: 'and',
groupings: groupings
)
@videos = @query.result(distinct: true)
end
end
class Video < ActiveRecord::Base
acts_as_taggable_on :type
end
class SearchesController < ApplicationController
def video
groupings = [] # 空配列生成
# パラメーターがあれば分割し、複数のAND条件分を生成する
if params[:q].present?
keywords = params[:q][:type_name_cont].split(/[\p{blank}\s]+/)
keywords.each { |value| groupings.push(type_name_cont: value) }
end
# 生成したAND条件を検索する。初期の場合、全件出力
@query = Video.ransack(
combinator: 'and',
groupings: groupings
)
@videos = @query.result(distinct: true)
end
end
検索用のErbは以下のような感じ。
<%= search_form_for @query, url: searches_video_path, method: :post do |f| %>
<!-- 検索窓 -->
<div class="form-group">
<label>フリーワード検索</label><br />
<%= f.search_field :type_name_cont,
class: 'form-control',
value: params.dig(:q, :type_name_cont) %>
<small class="help-block">※スペースで区切ることで複合検索ができます</small>
</div>
<% end %>
Rails.application.routes.draw do
# 動画検索
get 'searches/video' => 'searches#video'
post 'searches/video' => 'searches#video'
end
ポイント1
ネット上の記事では、tags_nameとなっているものが多いが…
ここではmodelで指定したtypeがデータベースでcontextとして扱われるためRansackの検索では、type_nameと記述すること。
例えば、標準のままのacts_as_taggableだけの場合は、tags_nameとなる。
ポイント2
ANDの複合検索のためにparams[:q]を再構築する。
再構築したものをRansackに代入する。
combinatorをorにするとor検索となる
# パラメーターがあれば分割し、複数のAND条件分を生成する
if params[:q].present?
keywords = params[:q][:type_name_cont].split(/[\p{blank}\s]+/)
keywords.each { |value| groupings.push(type_name_cont: value) }
end
ポイント3
このままだと検索後に検索窓に結果が残らないという事態に遭遇するので、フォームのvalueにparams.digを指定する
ポイント4
このままの実装だと、重複した結果が出力される可能性があるため、distinctを有効にする
最後に
ネット上のいろいろなサイトを潜りましたがなかなか良い回答が見つけにくかったので、残しておきます。
特にRansacを使用した複合検索をしたい方は、多いのではないでしょうか。
Author And Source
この問題について(acts-as-taggable-onとRansackを使用したタグの複合検索), 我々は、より多くの情報をここで見つけました https://qiita.com/ytojima/items/5b5c42a463b8e00c0edd著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .