行いたいこと
本の一覧を条件を指定して並び替える
今回の条件
- 投稿日の新しい順
- 投稿日の古い順
- 評価の高い順
環境
- Ruby3.1.2
- Rails6.1.7
- Bookモデル作成済み
- 評価機能作成済み(並び替えで使用しているだけなので必須ではない)
1.並び替える方法
order
を用いてデータを並び替える
Book.order(条件: :並び順)
Book.order(created_at: :desc) created_at:は作成日時。 :descは降順
Book.order(created_at: :asc) created_at:は作成日時。 :ascは昇順
Book.order(rating: :desc) ratingは評価の値が入っているカラム名
勿論このまま書いてもいいが、コントローラーをスッキリさせるためscope
を用いて簡潔にする
models/book.rb
scope :sort_rate, ->{order(rating: :desc)}
scope :sort_new, ->{order(created_at: :desc)}
scope :sort_old, ->{order(created_at: :asc)}
2.viewでのリンクの作成
view各検索方法へとアクセスするリンクを作成する
views/books/index.erb
~省略~
<h2>Books</h2>
<p><%= link_to '新しい順', books_path(new:new)%> |
<%= link_to '古い順', books_path(old:old)%> |
<%= link_to '評価の高い順', books_path(rate:rate)%></p>
~省略~
ここでのbooks_path(new:"new")
、books_path(old:"old")
、books_path(rate:"rate")
は送信先は全てindexになるが、さらに( )の中の値を一緒に送信している
例:books_path(new:"new")
ならnew:
という項目にnew
という値を付与
この( )の値は任意のもので良い。後述するコントローラーでの分岐に必要になる
3.コントローラーでの分岐処理
indexアクションを以下のように変更
controller/books_controller.rb
def index
if params[:rate].present?
@books = Book.sort_rate
elsif params[:new].present?
@books = Book.sort_new
elsif params[:old].present?
@books = Book.sort_old
else
@books = Book.all
end
@book = Book.new
end
ここで仮に「新しい順」を押した時に送られる値を確認してみる
[1] pry(#<BooksController>)> params
=> #<ActionController::Parameters {"new"=>"new", "controller"=>"books", "action"=>"index"} permitted: false>
"new"=>"new"
という値が送られてきているのがわかる。
あとはif params[:~~].present? でその値が有るかを確認し、
合致する場所の処理を、1で設定したscope
を用いて記述していく
※present? はその要素が存在していればtrue
、なければfalse
を返す。
これで完成!
参考にした記事