ポートフォリオにソート機能を実装した時のメモ。
完成イメージ
実装と解説
今回実装したのは投稿されたイベントを新着順、古い順、イベントの参加者数順に並び替える機能です。
① ルーティングの定義
example.com/?sort_new
→ 新しい順に並び替え のように、
パラメーターの変更で並び替えできるようにルーティングを変更していきます。
congig/routes.rb
get 'events/search/sort_new', to: 'events#search', as: 'sort_new'
get 'events/search/sort_old', to: 'events#search', as: 'sort_old'
get 'events/search/sort_join', to: 'events#search', as: 'sort_join'
② scope定義
並び替えるためのscopeをそれぞれ定義します。
app/models/event.rb
scope :latest, -> {order(updated_at: :desc)}
scope :old, -> {order(updated_at: :asc)}
scope :join_count, -> { includes(:joins).sort {|a,b| b.joins.size <=> a.joins.size}}
解説
scope :join_count, -> { includes(:joins).sort {|a,b| b.joins.size <=> a.joins.size}}
b.joins.size
とa.joins.size
はそれぞれ参加の数を表しています。
それをsort
メソッドを使って昇順に並び替えています。
② Controllerで分岐
scopeをControllerで定義しパラメーターで分岐して使用できるようにします。
ページネーションにはkaminariを使用しています。
app/controllers/events_controller.rb
if params[:new]
@events = Event.latest.page(params[:page]).per(PER_PAGE)
elsif params[:old]
@events = Event.old.page(params[:page]).per(PER_PAGE)
elsif params[:join]
events = Event.join_count
@events = Kaminari.paginate_array(events).page(params[:page]).per(PER_PAGE)
end
③ ソートリンクをViewに追加して反映
最後にViewでパラメーター変更のためのリンクを追加します。
app/
.sort-container
%ul.sort
%li 並び順
%li
= link_to '新着', events_search_path(new: 'true'), {class: 'sort-link' "#{'active' if current_page?('/events/search?new=true')}"}
%li
= link_to '古い', events_search_path(old: 'true'), {class: 'sort-link' "#{'active' if current_page?('/events/search?old=true')}"}
%li
= link_to '参加者数', events_search_path(join: 'true'), {class: 'sort-link' "#{'active' if current_page?('/events/search?join=true')}"}
解説
"#{'active' if current_page?('/events/search?new=true')}"
link_toにつけた上の部分は/events/search?new=true
のページつまり、新着順に並び替えられているページにおいてactive
というクラスをつけるという書き方です。
これをすることで完成イメージのようにHTMLを動的に変更することができます。
あとはお好みでスタイルを当てれば完成です!