積々RUNMIZZO

日々積み重ね

【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から異なる変数を受け取れる
  • ってことでそれぞれのrenderでurlオプションを指定

    • url: boards_path
    • url: bookmarks_boards_path


以上。


参照


ransackで検索機能を実装する - Ruby on Rails Learning Diary

【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)


掲示板のページネーション - olive_miuのブログ

【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

rails-i18n/ja.yml at master · svenfuchs/rails-i18n · GitHub

present? と any? の使い分けを読み手の気持ちになって考える - Qiita

【Ruby on Rails】コメント投稿だけAjax化(超ざっくり)

学習メモです✍

  1. コメントの投稿フォームのform_withのlocal: trueを削除(※デフォルトでremote: trueだから)
  2. redirect_backの処理を削除(更にcreateメソッドで簡潔化)
  3. jsファイル作成
$("#js-table-comment").prepend("<%= j(render('comments/comment', comment: @comment)) %>");

prependは投稿内容を1番前に表示させる
htmlとかreplaceWithやったらゴソッと他の投稿消えるから一瞬焦る※更新したら元通り)
→この辺の記述の仕組みは後で復習

$("textarea").val('');

→コメント作成後、フォームを空にする


おまけ


$(セレクタ).メソッド(引数)はjQueryの省略構文 Image from Gyazo
これだけでかなり理解◎

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的に呼び出してくれたってことかな。

参照


jQueryの使い方「基本の書き方と考え方」
RailsでAjax基本形(Scaffoldで学ぶ) - Qiita

【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関数を使った形式

  1. リダイレクト処理していたアクションを変更
    • redirect_back等の記述がせれていたら削除
  2. Ajaxでサーバーにリクエストを送る処理を追加
    • ヘルパーにremote: trueを指定
    • レンダリングが、htmlではなくjsファイルで実行される
  3. 実行したい内容を記載した jsファイル(js.erb)を作成
    • htmlメソッド(もしくはreplaceWithメソッド)を用い、指定したセレクタのhtml部分(指定したid属性を持つ部分)を置き換える

(例)

$("#js-bookmark-button-for-board-<%= @board.id %>").replaceWith("<%= j(render('boards/unbookmark', board: @board)) %>");

参照

Ajaxでブックマークボタンを実装する - Ruby on Rails Learning Diary

【Ruby on Rails】ページ移動してくれなかった時の話

本日のお悩み解決体験です。

掲示板アプリの作成中、一覧ページから詳細ページに飛ばない現象に遭遇。

<%= link_to board.title, boards_path(board) %>

※パーシャルで@は省略してるのは良いとして、、
boardsさん、sが余計ですね。

<%= link_to board.title, board_path(board) %>

これでOKかと思ったら、、
Image from Gyazo
どーん

そんなファイルねぇよ、、だと?
あ、
Image from Gyazo
showファイルよ、何故お前がそこに。
あなたはboardsコントローラ所属で、

resources :boards, only: %i[index create new show] do
  resources :comments, only: %i[create], shallow: true
end

ルーティングもこの通り。

ファイルをboardsディレクトリに移動させて一件落着。

コードは友達◎