機能武装していきます。
まず初めに
Seedsでサンプルデータ投入
fakerを利用してサンプルデータを大量に投入する。
Gemfileにgem 'faker'
を記入してbundle
[ Gemfile ]
gem 'faker'
% bundle
seedsファイルを編集します。
[ db/seeds.rb ]
# ユーザー User.create!( [ { name: 'panda', email: 'panda@example', password: 'password', password_confirmation: 'password', }, { name: 'rakuda', email: 'rakuda@example.com', password: 'password', password_confirmation: 'password' }, { name: 'tamanegi', email: 'tamanegi@example.com', password: 'password', password_confirmation: 'password' }, ] ) # タスク users = User.all 30.times do title = Faker::JapaneseMedia::SwordArtOnline.game_name description = Faker::JapaneseMedia::SwordArtOnline.location users.each { |user| user.tasks.create!(title: title, description: description) } end
ユーザーを3人作成して、各ユーザーに30タスクを作ります。
% rails db:reset db:seed Dropped database 'db/development.sqlite3' Dropped database 'db/test.sqlite3' Created database 'db/development.sqlite3' Created database 'db/test.sqlite3'
fakerについては ↓
GitHub - faker-ruby/faker: A library for generating fake data such as names, addresses, and phone numbers.
いろいろなサンプルデータがあって面白い
Ransackで検索機能
Tasksの一覧画面に検索機能をつけていくっ
GitHub - activerecord-hackery/ransack: Object-based searching.
に書いてある通り進めていきます。
Gemfileにransack
を記入しbundle
[ Gemfile ]
gem 'ransack'
bundle
ここで、サーバーを起動中であれば再起動する。
続いて、コントローラーのindexアクションを編集します
[ tasks_controller.rb ]
def index @q = current_user.tasks.ransack(params[:q]) @tasks = @q.result(distinct: true).recent end
ビューに検索フォームを追加します
[ tasks/index.html.slim ]
h1 タスク一覧 .nav = link_to '新規登録', new_task_path, class: 'nav-link' .row.justify-content-end = search_form_for @q, class: 'mb-5 ' do |f| .form-inline = f.label :title_cont, 'タイトル', class: 'my-1 mr-2' = f.search_field :title_cont, class: 'my-1 mr-sm-2' = f.submit '検索', class: 'btn btn-primary my-1' table.table thead.thead-default tr th タイトル (省略)
検索機能がちゃんと動いていることもKiritoで確認!
[ コンソール ]
Parameters: {"q"=>{"title_cont"=>"kirito"}, "commit"=>"検索"} User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]] ↳ app/controllers/application_controller.rb:8:in `current_user' Rendering tasks/index.html.slim within layouts/application Task Load (0.3ms) SELECT DISTINCT "tasks".* FROM "tasks" WHERE "tasks"."user_id" = ? AND "tasks"."title" LIKE '%kirito%' ORDER BY "tasks"."created_at" DESC [["user_id", 1]]
logを確認すると"title" LIKE '%kirito%
と書いてあります
検索した文字列を含むものは全てokみたいなので試しにki
だけで検索してみます。
もっと表示されるかと思いましたが・・・
タイトルにki
を含む全てのtaskが表示されました!
ActiveStorageで画像添付機能
ActiveStorageとは、ファイル管理gemのことです。
Rails5.2から標準搭載となったのでGemfileに書いてbundleする作業は不要です
environment環境で利用する場合は保存先の設定をする必要があります。今回はdevelopment環境で使う設定でやります。environment環境の設定は後日やります・・・
詳しくは、Active Storage の概要 - Railsガイド
gem自体はインストール不要ですが、下記コマンドでActiveStoragを使えるようにする必要があります。
% rails active_storage:install Copied migration 20200119130415_create_active_storage_tables.active_storage.rb from active_storage
すると、下記マイグレーションファイルが作成されます。
[ db/migration/??????????create_active_storage_tables.active_storage.rb ]_
# This migration comes from active_storage (originally 20170806125915) class CreateActiveStorageTables < ActiveRecord::Migration[5.2] def change create_table :active_storage_blobs do |t| t.string :key, null: false t.string :filename, null: false t.string :content_type t.text :metadata t.bigint :byte_size, null: false t.string :checksum, null: false t.datetime :created_at, null: false t.index [ :key ], unique: true end create_table :active_storage_attachments do |t| t.string :name, null: false t.references :record, null: false, polymorphic: true, index: false t.references :blob, null: false t.datetime :created_at, null: false t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true t.foreign_key :active_storage_blobs, column: :blob_id end end end
2種類のtableが作成されてそこに Active Storage の概要 - Railsガイド
準備が整いましたので実装していきます
[ models/task.rb ]
class Task < ApplicationRecord validates :title, presence: true, length: { maximum: 30 } validates :description, presence: true has_one_attached :image # 追加 belongs_to :user scope :recent, -> { order(created_at: :desc) } end
has_one_attached
メソッドを使い、1つのTaskにつき1つの画像を添付できるようになります。その画像はimage
として呼ぶことができます。
画像を添付するためのformを追加します。
[ views/tasks/_form.html.slim ]
(省略) = form_with model: task, local: true do |f| .form-group = f.label :title, 'タイトル' = f.text_field :title, class: 'form-control', id: 'task_title' .form-group = f.label :description, '詳細' = f.text_area :description, class: 'form-control', id: 'task_description' .form-group # 追加 = f.label :image, '画像' # 追加 = f.file_field :image, class: 'form-control', id: 'task_image' # 追加 = f.submit '登録', class: 'btn btn-success'
こんな感じ
StrongParametersにimageを追加します
[ tasks_controller.rb ]
(省略) private def task_params params.require(:task).permit(:title, :description, :image) <- :image追加 end (省略)
viewにimageできるようにする
[ views/tasks/show.html.slim ]
(省略) th 詳細 td = @task.description tr th 画像 td = image_tag @task.image if @task.image.attached? tr th 登録日 td = @task.created_at (省略)
全てのTaskに画像添付したいわけではないので、if @task.image.attached?
をつけます。
これがないと画像がなかったときにエラーとなってしまいます。
機能が正常に動くか確認します。
無事、画像の添付に成功しました!!
Kaminariでページネーション
現在一覧画面に30件のタスクが表示されています。
これから増えていけば増えていくほどページの読み込みが遅くなります。
こりゃいかん
[ Gemfile ]
gem 'kaminari'
% bundle
さっそくコントローラーの設定から行きますっ
[ tasks_controller.rb ]
(省略) def index @q = current_user.tasks.ransack(params[:q]) @tasks = @q.result(distinct: true).recent.page(params[:page]) end (省略)
続いてview
[ views/tasks/index.html.slim ]
(省略) .row.justify-content-end = search_form_for @q, class: 'mb-5 ' do |f| .form-inline = f.label :title_cont, 'タイトル', class: 'my-1 mr-2' = f.search_field :title_cont, class: 'my-1 mr-sm-2' = f.submit '検索', class: 'btn btn-primary my-1' .mb-3 = paginate @tasks = page_entries_info @tasks table.table thead.thead-default tr th タイトル th 登録日 (省略)
こんな感じ
gemをインストールしたらサーバーを再起動するのは基本中の基本です。
[ コンソール ]
サーバー再起動
そして
うまく表示されました!
しか〜し!
なぜ英語なのか
デフォルトの表示件数が25件/ページなのでもっと減らしたい
表記を日本語にする
config/locales
にkaminari.ja.yml
と言うファイルを作成します。
そして、ちょっと面倒ですが下記内容を記述します
[ config/locales/kaminari.ja.yml ]
ja: views: pagination: first: "« 最初" last: "最後 »" previous: "‹ 前" next: "次 ›" truncate: "…" helpers: page_entries_info: one_page: display_entries: zero: "%{entry_name}がありません" one: "1件の%{entry_name}が表示されています" other: "%{count} 件の%{entry_name}が表示されています" more_pages: display_entries: "全%{total} 件中 %{first} - %{last} 件の%{entry_name}が表示されています"
次に、
config/initializers
にlocale.rb
と言うファイルを作成し、下記を記述します
[ config/initializers/locale.rb ]
Rails.application.config.i18n.default_locale = :ja
そして、
[ コンソール ]
サーバー再起動
すると・・・
tasks
以外は日本語になりました!(tasksはまた別の場所で設定する必要があるため今回はパス)
しかしデザインが今市なので、Bootstrapを使います。(bootstrapは導入済みです)
[ コンソール ]
% rails g kaminari:views bootstrap4 Running via Spring preloader in process 2902 downloading app/views/kaminari/_first_page.html.slim from kaminari_themes... create app/views/kaminari/_first_page.html.slim downloading app/views/kaminari/_gap.html.slim from kaminari_themes... create app/views/kaminari/_gap.html.slim downloading app/views/kaminari/_last_page.html.slim from kamina (省略)
こんだけです
いい感じになりました^^
残るは表示件数の調整
表示件数の変更方法は3通り?あるんですが、一番簡単なやつ
[ tasks_controller.rb ]
(省略) def index @q = current_user.tasks.ransack(params[:q]) @tasks = @q.result(distinct: true).recent.page(params[:page]).per(6) end (省略)
per(6)
をつけるだけです *()内の数字を自由に入れてください
スクロールなしで表示できるのは6件でした!
今回は以上です!
次回、後でやるをやるお