質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

解決済

1回答

731閲覧

railsで検索機能を実装したいが、検索結果ではなく一覧が表示されてしまう

annasui

総合スコア1

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

0クリップ

投稿2021/10/10 12:38

編集2021/10/11 10:05

前提・実現したいこと

railsで趣味を登録、検索できるサービスを作ろうとしています。

発生している問題・エラーメッセージ

index画面で検索機能を実装したいのですが、フォームに検索ワードを打ち込んでも常に一覧が表示されます。

該当のソースコード

view/user/hobbies/index.html.erb

<div class="table-wrapper"> <%= render "search_form" %> <table class="listing"> <!- search結果が一覧になる-> <% @hobbies.each do |h| %> <% p = HobbyPresenter.new(h, self) %> <tr> <td><%= p.name %></td> <td><%= p.initial_investment %></td> <td><%= p.running_cost %></td> <td><%= p.frequency %></td> <td><%= p.place %></td> <td><%= p.number %></td> </tr> <% end %> </table> </div>

view/user/hobbies/_search_form.html.erb

<%= form_with model: @search_form, scope: "search", url: :user_hobbies, html: { method: :get, class: "search" } do |f| %> <%= markup do |m| p = FormPresenter.new(f, self) m << p.text_field_block(:name, "名称:") m.br m << p.text_field_block(:initial_investment, "初期投資:") m << p.text_field_block(:running_cost, "ランニングコスト:") m.br m << p.text_field_block(:frequency, "頻度:") m << p.text_field_block(:place, "場所:") m << p.text_field_block(:number, "人数:") m.br m << f.submit("検索") end %> <% end %>

form/user/hobby_search_form.rb(修正後)

class User::HobbySearchForm include ActiveModel::Model attr_accessor :name, :initial_investment, :running_cost, :frequency, :place, :number def initialize(search_params = {}) @name = search_params[:name] @initial_investment = search_params[:initial_investment] @running_cost = search_params[:running_cost] @frequency = search_params[:frequency] @place = search_params[:place] @number = search_params[:number] end def search rel = Hobby if name.present? rel = rel.where(name: name) end rel = rel.where(initial_investment: initial_investment) if initial_investment.present? rel = rel.where(running_cost: running_cost) if running_cost.present? rel = rel.where(frequency: frequency) if frequency.present? rel = rel.where(place: place) if place.present? rel = rel.where(number: number) if number.present? rel.order(:id) end end

試したこと

Rails実践ガイドの機能拡張編を参考にしながらやってみたのですが、実力不足すぎてこの不具合に何時間も足止めされています。

補足情報(FW/ツールのバージョンなど)

presenters/form_presenter.rb

class FormPresenter include HtmlBuilder attr_reader :form_builder, :view_context delegate :label, :text_field, :date_field, :password_field, :check_box, :radio_button, :text_area, :object, to: :form_builder def initialize(form_builder, view_context) @form_builder = form_builder @view_context = view_context end def notes markup(:div, class: "notes") do |m| m.span "*", class: "mark" m.text "印の付いた項目は入力必須です。" end end def text_field_block(name, label_text, options = {}) markup(:div, class: "input-block") do |m| m << decorated_label(name, label_text, options) m << text_field(name, options) m << error_messages_for(name) end end def password_field_block(name, label_text, options = {}) markup(:div, class: "input-block") do |m| m << decorated_label(name, label_text, options) m << password_field(name, options) m << error_messages_for(name) end end def date_field_block(name, label_text, options = {}) markup(:div, class: "input-block") do |m| m << decorated_label(name, label_text, options) m << date_field(name, options) m << error_messages_for(name) end end def drop_down_list_block(name, label_text, choices, options = {}) markup(:div, class: "input-block") do |m| m << decorated_label(name, label_text, options) m << form_builder.select(name, choices, { include_blank: true }, options) m << error_messages_for(name) end end def error_messages_for(name) markup do |m| object.errors.full_messages_for(name).each do |message| m.div(class: "error-message") do |m| m.text message end end end end def decorated_label(name, label_text, options = {}) label(name, label_text, class: options[:required] ? "required" : nil) end end

presenters/hobby_presenter.rb

class FormPresenter include HtmlBuilder attr_reader :form_builder, :view_context delegate :label, :text_field, :date_field, :password_field, :check_box, :radio_button, :text_area, :object, to: :form_builder def initialize(form_builder, view_context) @form_builder = form_builder @view_context = view_context end def notes markup(:div, class: "notes") do |m| m.span "*", class: "mark" m.text "印の付いた項目は入力必須です。" end end def text_field_block(name, label_text, options = {}) markup(:div, class: "input-block") do |m| m << decorated_label(name, label_text, options) m << text_field(name, options) m << error_messages_for(name) end end def password_field_block(name, label_text, options = {}) markup(:div, class: "input-block") do |m| m << decorated_label(name, label_text, options) m << password_field(name, options) m << error_messages_for(name) end end def date_field_block(name, label_text, options = {}) markup(:div, class: "input-block") do |m| m << decorated_label(name, label_text, options) m << date_field(name, options) m << error_messages_for(name) end end def drop_down_list_block(name, label_text, choices, options = {}) markup(:div, class: "input-block") do |m| m << decorated_label(name, label_text, options) m << form_builder.select(name, choices, { include_blank: true }, options) m << error_messages_for(name) end end def error_messages_for(name) markup do |m| object.errors.full_messages_for(name).each do |message| m.div(class: "error-message") do |m| m.text message end end end end def decorated_label(name, label_text, options = {}) label(name, label_text, class: options[:required] ? "required" : nil) end end

controllers/user/hobbies_controller.rb(修正後)

class User::HobbiesController < User::Base def index @search_form = User::HobbySearchForm.new(search_params) @hobbies = @search_form.search end def new @hobby = Hobby.new end def create @hobby = Hobby.new(hobby_params) if @hobby.save redirect_to user_hobby_path(@hobby.id), notice: "Hobby #{@hobby.name}を登録しました" else render "new" end end def show @hobby = Hobby.find_by(params[:hobby_id]) end private def hobby_params params.permit(:name, :initial_investment, :running_cost, :frequency, :place, :number) end def search_params params.permit(:search).permit(:name, :initial_investment, :running_cost, :frequency, :place, :number) end end

検索時のログ

Hobby Load (0.6ms) SELECT "hobbies".* FROM "hobbies" WHERE "hobbies"."name" = $1 ORDER BY "hobbies"."id" ASC [["name", "ランニング"]]

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

懸念が一つ、間違いが一つ
懸念
params[:search]&.permit([ とありますが、 serach で来ているか Paramaters 確認してください。

間違い
@search_form = User::HobbySearchForm.new(search_params) でパラメータ渡してますが、class User::HobbySearchForm がinitialize していないので、使われて居ません。

追記
jj_pot さんの方法に従ってください。
@name = search_params[:name] のように。

で、

またUser::HobbySearchForm内ではsearch_paramsを呼び出せないのですが、どういう意味でしょうか?お手数おかけします。

あなたが def initialize(search_params = {}) と書いているので、その search_params を使っているだけです。
Controller の search_params ではないです

投稿2021/10/10 23:33

編集2021/10/11 09:03
winterboum

総合スコア23567

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

annasui

2021/10/11 00:20

懸念に関しては、ログに以下のように表示されているので問題ないかと思います。間違いの方に関しては、class User::HobbySearchFormの中にinitializeメソッドを書くということでしょうか?改善の仕方がわからなかったので、もう少し調べてみます。Parameters: {"search"=>{"name"=>"ランニング", "initial_investment"=>"", "running_cost"=>"", "frequency"=>"", "place"=>"", "number"=>""}, "commit"=>"検索"}
annasui

2021/10/11 00:39

下のように(User::HobbySearchFormに)追記してみましたが、改善しませんでした。 def initialize(search_params = {}) @name = name @initial_investment = initial_investment @running_cost = running_cost @frequency = frequency @place = place @number = number end
jj_pot

2021/10/11 05:54 編集

permitの中は配列ではないのでは?それと、initializeですが、@name = search_params[:name]とかじゃないかな
annasui

2021/10/11 05:22

単純にpermit(:name ...)としてもダメでした。またUser::HobbySearchForm内ではsearch_paramsを呼び出せないのですが、どういう意味でしょうか?お手数おかけします。
annasui

2021/10/11 09:27

何度も解答ありがとうございます。@name = search_params[:name]としてみたのですが、undefined method `[]' for nil:NilClassと表示されうまくいきませんでした。permitのところが間違っているのかと思い、permit(:name..)でも試してみましたがダメでした。
winterboum

2021/10/11 09:31

「undefined method `[]' for nil:NilClassと表示され」それはおかしいな。 def initialize(search_params = {}) とかいてあるなら、 送られてくる引数が nil であったなら {} になるから、そのエラーにはなら無いはず。
winterboum

2021/10/11 09:36

あと、 params[:search]&.permit( が違和感。 params.permit(:search).permit がよく使われる
annasui

2021/10/11 09:51

params.permit(:search).permitにして試したところ、index画面までは表示されましたが検索を実行するとUnpermitted parameters: :search, :commitというエラーがコマンドに表示されました。何度も申し訳ないので、これ以上厳しそうでしたら他のやり方で検索機能に挑戦してみます。
winterboum

2021/10/11 09:56

どの様になおしたのか、 がcodeで示されないので、的確な助言ができないのです。
annasui

2021/10/11 10:07

なるほど、申し訳ないです。一応コードの修正を書きました。
winterboum

2021/10/11 12:49

「Unpermitted parameters:」はエラーというより警告なので、permitされているべきものが出たらやっかいですが、でなければあまり気にせんでも。 で、 気になるのは 検索時のログ の通りなら、indexにでません?
annasui

2021/10/11 12:56

大変申し訳ないのですが自分には不相応な実装方法かと思ったので、別の方法を試して見ることにします。この先不具合が出ても自走できないと思いました。ここまで親切にありがとうございました。ちなみにindexは常に一覧が表示されました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問