railsでform_withを使用した検索機能を作ってみよう
railsの検索機能の記事はたくさんあるのですが、どれもform_tagでの実装であるので今回はrails 5.2.4~向けのform_withを使用して実装をしようかと思います。
複数のモデルでの条件分岐や,一致条件での条件分岐もおこなっています
バージョン
- ruby 2.6.3
- rails 5.2.4
- bootstrap 4.2.5
実装イメージ
検索に必要なファイルやモデルを作成
- ターミナルで下記を作成
- rails g model モデル名
rails g controller books index
rails g controller searchs top
ルーティング設定
routes.rb
resourecs: books,only: :index
get 'searchs/about', to: "searchs#top" ,as: search
検索機能のコードを作成
books/index.html.erb
<%= form_with(url: search_path,method: :get,local: true) do |f| %>
<%= f.text_field :search %>
<%= f.select :model , options_for_select({User: :user,Book: :book })%>
<%= f.select :how , options_for_select({完全一致: :"0",前方一致: :"1",後方一致: :"2",部分一致: :"3" })%>
<%= f.submit 'Search'%>
<% end %>
上記のコードの説明
<%= form_with(url: search_path,method: :get,local: true) do |f| %>
# 検索結果を表示したいurlの指定します.
<%= f.text_field :search %>
# 検索するワードを searchという架空のカラムに格納される
<%#= f.select :model , options_for_select({User: :user,Book: :book })%>
# 検索したモデルをセレクトで選択でき,接頭文字が大文字の方が表示されるもの、接頭文字が小文字のものがmodelと言う架空のカラムに格納される
<%#= f.select :how , options_for_select({完全一致: :"0",前方一致: :"1",後方一致: :"2",部分一致: :"3" })%>
# 検索する際の条件のセレクトで選択した条件によってhowと言う架空のカラムに0~3のいづれかが格納される
コントローラーのアクション設定
searchs_controller.rb
def top
if params[:search].present?
if params[:model] == "user"
if params[:how] == "0"
@users =User.where("name LIKE ?", "#{params[:search]}")
elsif params[:how] == "1"
@users =User.where("name LIKE ?", "#{params[:search]}%")
elsif params[:how] == "2"
@users =User.where("name LIKE ?", "%#{params[:search]}")
else
@users = User.where(['name LIKE ?', "%#{params[:search]}%"])
end
elsif params[:model] == "book"
if params[:how] == "0"
@books =Book.where("title LIKE ?", "#{params[:search]}")
elsif params[:how] == "1"
@books =Book.where("title LIKE ?", "#{params[:search]}%")
elsif params[:how] == "2"
@books =Book.where("title LIKE ?", "%#{params[:search]}")
else
@books = Book.where(['title LIKE ?', "%#{params[:search]}%"])
end
end
end
end
viewページで設定した架空のカラムでの条件分岐が大事です!
最初の1行では値格納されているかの確認をします
params[:model]でmodelに格納した値をの中身でuserモデルかbookモデルかの条件分岐を行います
params[:how]で一致する条件完全一致なのか,前半一致なのかなどの条件分岐を行います
それぞれ条件がととなった際に値を変数に入れviewページで表示させています
検索結果の表示
search.top.html
<% if params[:search].present? %>
<% if params[:model] == "user" %>
<% @users.each do |f| %>
<%= f.name %>
<% end %>
<% elsif params[:model] == "book"%>
<% @books.each do |f| %>
<%= f.title %>
<% end %>
<% end %>
<% else %>
検索結果は存在ません
<% end %>
これでうまくいくと思いますwww
ちなみに綺麗にするならモデルにメソッドを作りましょう
user.rb
def self.search(how,value)
if how == "0"
@users =User.where("name LIKE ?", "#{value}")
elsif how == "1"
@users =User.where("name LIKE ?", "#{value}%")
elsif how == "2"
@users =User.where("name LIKE ?", "%#{value}")
else
@users = User.where(['name LIKE ?', "%#{value}%"])
end
end
book.rb
def self.search(how,value)
if how == "0"
@books =Book.where("title LIKE ?", "#{value}")
elsif how == "1"
@books =Book.where("title LIKE ?", "#{value}%")
elsif how == "2"
@books =Book.where("title LIKE ?", "%#{value}")
else
@books = Book.where(['title LIKE ?', "%#{value}%"])
end
end
searchs_controller.rb
def top
if params[:search].present?
if params[:model] == "user"
@users =User.search(params[:how],params[:search])
elsif params[:model] == "book"
@books =Book.search(params[:how],params[:search])
end
end
end
こちらの方がスッキリですね!
参考文献
https://qiita.com/rised/items/3d4cffe82ac46ee445ea
https://qiita.com/Yusuke_Hoirta/items/159e63bcc5e99958d698