【Ruby on Rails】検索機能の実装(ransack)
本日もざっくり学習メモ✍
gem 'ransack'をインストール
ransackにはシンプルモードとアドバンスモードがあるらしい(今回はシンプルモード)
コントローラー
def index @q = Board.ransack(params[:q]) @boards = @q.result(distinct: true).includes(:user).order(created_at: :desc).page(params[:page]) end
用語 | 説明 |
---|---|
params[:q] | Viewファイルから送られてくるパラメーター |
ransackメソッド | 送られてきたパラメーターを元にテーブルからデータを検索するメソッド(リクエストが無ければ全件を返す) |
resultメソッド | ActiveRecord_Relationのオブジェクトに変換する |
distinct: true | 子テーブルから取得するデータの重複を取り除く(今回コメントは検索しないから無くてもいける) |
- ビュー
<%= search_form_for @q do |f| %> <div class="input-group mb-3"> <%= f.search_field :title_or_body_cont, class:"form-control", placeholder: '検索ワード' %> <div class="input-group-append"> <%= f.submit "検索", class: "btn btn-primary" %> </div> </div> <% end %>
用語 | 説明 |
---|---|
search_form_for | form_forの検索フォームバージョンみたいなもの |
f.search_field :title_or_body_cont, ~ | titleとbodyカラムに対して_contで部分一致検索を可能にしている |
Bookmark一覧にも実装
- urlを指定しないとリクエストが/boardsになってしまってindexページでの結果になる
- 何故?(上の
@q
が先に読み込まれるから?)📝
- 何故?(上の
<%= search_form_for @q, url: bookmarks_boards_path do |f| %>
ここで基本Viewが同じなのでパーシャる
- search_form_forのurlオプションを
url: url
にしたら、それぞれのrenderから異なる変数を受け取れる
- search_form_forのurlオプションを
ってことでそれぞれのrenderでurlオプションを指定
url: boards_path
url: bookmarks_boards_path
以上。
参照
【Ruby on Rails】ページネイション実装
2021/9/8学習メモ✍
本日もざっくりいきます!
gem 'kaminari'を追加してbundle
デフォルトファイル作成
rails g kaminari:config
- 1ページあたり20件表示に設定
config.default_per_page = 20
- コントローラーに追記
.page(params[:page])
- (コントローラーでも表示件数設定できるらしい)
.per(20)
→推奨されてない?
- bootstrap4のレイアウトを適用
rails g kaminari:views bootstrap4
→kaminariディレクトリに沢山ファイルがお出ましになられる。
- viewに表示させる
<%= paginate @objects %>
- ブックマーク一覧ページにも実装して完了
参照(いつもAZMS)
【Ruby on Rails】空欄投稿で処理が失敗した場合のメッセージ表示
2021/9/7学習メモです✍
投稿フォームにid追加
<%= form_with model: comment, url: [board, comment], id: 'new_comment' do |f| %>
からのcreate.js.erbファイルで
$("#error_messages").remove() <% if @comment.errors.present? %> $("#new_comment").prepend("<%= j(render('shared/error_messages', object: @comment)) %>") <% else %> $("#js-table-comment").prepend("<%= j(render('comments/comment', comment: @comment)) %>") $("textarea").val('') <% end %>
でOK!
なぜこれで動くかについては
以前、ユーザー登録やログイン実装辺りで
<% if object.errors.any? %> <div class="alert alert-danger"> <ul class="mb-0"> <% object.errors.full_messages.each do |msg| %> <li><%= msg %></li> <% end %> </ul> </div> <% end %>
を部分テンプレート化してたから。
そしてrender('shared/error_messages', object: @comment)
で呼び出されてるだけ◎
効率的!
エラー文の日本語化もi18nで設定済みでした。
おまけ
$("#error_messages").remove()
でメッセージが増え続けるのを防いでいる。.present?
は、オブジェクトが存在すればtrueを返し、存在しなければfalseを返すメソッド.any?
でもいける?と思い試したらいけたけど調べたら微妙に違う扱いらしい。
- ここでの
prepend
は入力フォームより前に表示するように使われている
参照
コメント投稿、削除機能のajax化 - olive_miuのブログ
【Rails】 | Pikawaka - ピカ1わかりやすいプログラミング用語サイト
【Rails】バリデーションのエラーメッセージを取得・表示・日本語化する方法を完全解説!|TechTechMedia
【Ruby on Rails】コメント投稿だけAjax化(超ざっくり)
学習メモです✍
- コメントの投稿フォームのform_withのlocal: trueを削除(※デフォルトでremote: trueだから)
- redirect_backの処理を削除(更にcreateメソッドで簡潔化)
- jsファイル作成
$("#js-table-comment").prepend("<%= j(render('comments/comment', comment: @comment)) %>");
→prepend
は投稿内容を1番前に表示させる
(html
とかreplaceWith
やったらゴソッと他の投稿消えるから一瞬焦る※更新したら元通り)
→この辺の記述の仕組みは後で復習
$("textarea").val('');
→コメント作成後、フォームを空にする
おまけ
$(セレクタ).メソッド(引数)はjQueryの省略構文
これだけでかなり理解◎
jsファイルの記述もうちょい深入り
今回使われてるjQuery記述
表記 | 意味 |
---|---|
$(“p”) | p要素全てを指定 |
$(“#hoge”) | id=”hoge”の要素を指定 |
j はActionView::Helpers::JavaScriptHelper#escape_javascript
のエイリアスメソッド。
改行コード、シングルクオート、ダブルクオートをJavaScript用にエスケープしてくれるヘルパメソッド(のエイリアス)でerb が Ruby コードとして解釈した文字列をJavaScriptで正しく扱えるようにエスケープしてくれる。
→要はRubyコードをJSコード的にしてくれる奴(ざっくり)
今回の場合render('comments/comment', comment: @comment)
でパーシャルしてるファイルをJS的に呼び出してくれたってことかな。
参照
【Ruby on Rails】Ajax化について学習メモ✍
学習メモ📝
Ajax
- Asynchronous JavaScript + XML の略
- 非同期通信と呼ばれる通信方法
- 逆に同期通信は画面の切り替わりが起きる(画面が一瞬白くなる)
- 地図アプリで画面が切り替わらずに操作できるイメージ
RailsではUJS: Unobtrusive(控えめな)JavaScriptという、HTMLの中にJavaScriptを混入させないという意図に由来して、組み込みヘルパーが用意されている。
form_with ・・・フォームの作成を支援
link_to ・・・リンクの生成を支援
button_to ・・・ボタンの作成を支援
(※form_withはデフォルトでAjaxが利用できる)
実装方法
①remote:true形式←コチラ採用
②ajax関数を使った形式
- リダイレクト処理していたアクションを変更
- redirect_back等の記述がせれていたら削除
- Ajaxでサーバーにリクエストを送る処理を追加
- ヘルパーにremote: trueを指定
- レンダリングが、htmlではなくjsファイルで実行される
- 実行したい内容を記載した jsファイル(js.erb)を作成
- htmlメソッド(もしくはreplaceWithメソッド)を用い、指定したセレクタのhtml部分(指定したid属性を持つ部分)を置き換える
(例)
$("#js-bookmark-button-for-board-<%= @board.id %>").replaceWith("<%= j(render('boards/unbookmark', board: @board)) %>");
参照
【Ruby on Rails】ページ移動してくれなかった時の話
本日のお悩み解決体験です。
掲示板アプリの作成中、一覧ページから詳細ページに飛ばない現象に遭遇。
<%= link_to board.title, boards_path(board) %>
※パーシャルで@は省略してるのは良いとして、、
boardsさん、s
が余計ですね。
<%= link_to board.title, board_path(board) %>
そんなファイルねぇよ、、だと?
あ、
showファイルよ、何故お前がそこに。
あなたはboardsコントローラ所属で、
resources :boards, only: %i[index create new show] do resources :comments, only: %i[create], shallow: true end
ルーティングもこの通り。
ファイルをboardsディレクトリに移動させて一件落着。
コードは友達◎