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

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

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

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

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

Q&A

解決済

1回答

1807閲覧

enumを利用してcheck_boxを作成し絞り込み検索を行いたい。

suzaku

総合スコア1

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

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

1グッド

1クリップ

投稿2021/04/22 00:38

やりたいこと

現在railsでタスク管理アプリを作成しています。
enumで定義したタスクの状態を検索フォームにcheck_boxとして
(□未着手 □着手中 □完了)このような形で作成し、
絞り込み検索を行いたいです。

現在viewには上記のような形でcheck_boxは表示されているのですが、
絞り込みがうまく機能してくれません。

今まではradio_buttonで実装しており、問題なく機能していたのですが
複数選択や選択の取り消しなど、使い易さを考えてcheck_boxに変更したいと考えています。

現在のソースコード

model

ruby

1class Task < ApplicationRecord 2 3 enum status: { waiting: 0, working: 1, completed: 2 } 4 5 def self.status(status_by) 6 case status_by 7 when "waiting" 8 waiting 9 when "working" 10 working 11 when "completed" 12 completed 13 else 14 all 15 end 16 end 17end

controller

ruby

1class TasksController < ApplicationController 2 def index 3 @tasks = Task.name_like(params[:name]). 4 status(params[:status]). 5 order(sort_param) 6 @status = params[:status] 7 end

メソッドチェインで「タイトル」、「状態」、「並び替え」で検索できるように考えています。

index

html

1<%= form_with url: tasks_path, method: :get do |f| %> 2 <p> 3 <%= f.label :status, Task.human_attribute_name(:status) %> 4 <%= f.collection_check_boxes :status, Task.statuses, :first, :first do |s| %> 5  <%= s.check_box value: @status %> 6  <%= s.label { Task.human_attribute_name("status.#{s.text}")} %> 7 <% end %> 8 </p> 9 <p><%= f.submit "検索" %></p> 10<% end %>

試したこと

check_boxで一つを選択し検索ボタンを押してサーバのlogを見ると、statusparameterが配列の中身に問題がありそうなのと、そもそもcollection_check_boxesを使用するのが正しいのかが分かりません。

Started GET "/tasks?name=&status%5B%5D=&status%5B%5D=waiting&sort=new&commit=%E6%A4%9C%E7%B4%A2" for ::1 at 2021-04-22 09:00:01 +0900 Processing by TasksController#index as HTML Parameters: {"name"=>"", "status"=>["", "waiting"], "sort"=>"new", "commit"=>"検索"} Rendering layout layouts/application.html.erb Rendering tasks/index.html.erb within layouts/application Task Load (1.9ms) SELECT "tasks".* FROM "tasks" ORDER BY created_at DESC ↳ app/views/tasks/index.html.erb:39 Rendered tasks/index.html.erb within layouts/application (Duration: 10.0ms | Allocations: 7853) [Webpacker] Everything's up-to-date. Nothing to do Rendered layout layouts/application.html.erb (Duration: 16.0ms | Allocations: 11084) Completed 200 OK in 18ms (Views: 14.6ms | ActiveRecord: 1.9ms | Allocations: 12039)

バージョン情報

ruby 3.0.0
Rails 6.1.3.1

その他

radio_buttonで問題なく機能していた際のコードも載せておきます。

ruby

1<%= f.label(:status, Task.human_attribute_name(:status)) %> 2<%= f.collection_radio_buttons(:status, Task.statuses, :first, :first) do |r| %> 3 <%= r.radio_button(checked: r.value == params[:status]) %> 4 <%= f.label(Task.human_attribute_name("status.#{r.text}")) %> 5<% end %>

調べても情報が少ないため質問させていただきました。
実装のアドバイスをいただけると大変助かります。
よろしくお願いいたします。

shinoharat👍を押しています

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

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

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

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

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

shinoharat

2021/04/22 02:14 編集

> statusのparameterが配列の中身に問題がありそうなのと、そもそもcollection_check_boxesを使用するのが正しいのかが分かりません。 使うメソッドは「collection_check_boxes」で問題ありません。 配列の中身に問題があると推察されているようですが、未着手にチェックを入れて  "status"=>["", "waiting"] が送られてきたのであれば、動作としては想定通りな気がします。 なぜ問題があると思われたのでしょうか? (空文字が要らないって意味ですかね?)
suzaku

2021/04/22 02:30

レビューいただきありがとうございます! 配列の中身には問題はなかったのですね、問題があると考えた理由としては仰る通り空文字が要らないと思ったためです。選択した未着手が[ "waiting" ]として一つだけ渡されるものなのかと考えました。 私のcollection_check_boxesメソッド内の書き方に問題があるのでしょうか。
scivola

2021/04/22 03:50

やりたいことは,たとえば「着手中」と「完了」にチェックを入れた場合,〈status が「着手中」もしくは「完了」〉なレコードに絞り込む,ということでしょうか? もしそうなら Task モデルの status メソッドを変える必要がありますね。
suzaku

2021/04/22 04:49

> やりたいことは,たとえば「着手中」と「完了」にチェックを入れた場合,〈status が「着手中」もしくは「完了」〉なレコードに絞り込む,ということでしょうか? 説明が足らずすみません。その通りです。 確かにstatusメソッドの条件分岐がradio_buttonの時のままでした... ここを選択した状態を表示するように変えてあげないといけないということですね。
guest

回答1

0

ベストアンサー

rb

1Task.statuses.keys & ["", "working", "completed"]

rb

1["working", "completed"]

が取れると思います(Array#& は集合の積演算)。
一方

rb

1Task.where(role: ["working", "completed"])

とすると,「role の値が "working" もしくは "completed" である」という ActiveRecord_Relation が得られますよね。

以上をまとめると,Task.status メソッドはやめて,

rb

1scope :status, -> s { where role: Task.statuses.keys & s }

みたいなスコープを導入すればよさそうです。

なお,べつに Task.statuses.keys との積集合を取らなくても,単純に params[:status] から空文字列を削除してもいいですし,何なら空文字列を残したままでも検索結果は変わらないはずです。
しかし,ユーザーが自由に制御できる params[:status] の値をそのまま where に使うのはちょっとどうかと思ったので。

投稿2021/04/22 21:50

scivola

総合スコア2108

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

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

suzaku

2021/04/23 03:13

とても分かり易いご回答をいただきありがとうございます! 無事にチェックボックスを完成させることができました。 「Array#&」についてはRubyの勉強をする中で理解していたつもりでいましたが、実際にこういった形で実装の中での使い方を知ることができ、理解を深めることができました。 scopeとクラスメソッドの使い分けについても、今後勉強していきたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問