Ruby on Rails5速習実践ガイド chapter7
7-1 登録や編集の実行前に確認画面をはさむ
登録する前に確認画面が出てきてそこで確認してからデータが登録されるように設定する。
まずは確認画面が表示されるアクション(conform_newアクション)をコントローラーに書く
def confirm_new
@task = current_user.tasks.new(task_params)
render :new unless @task.valid? #もしデータベースに@taskがなかったら実行
その次にルーティングを記入
resources :tasks do
post :confirm, action: :confirm_new, on: :new
end
post :confirm, action: :confirm_new, on: :new
この部分は元々以下の形であった
resources :tasks do
new do
post :confirm, action: :confirm_new
end
end
newブロック内に要素が一つだけの場合は後ろにon: :ブロック名とすることでルーティングがかける
次に確認画面のビューを作る
h1 新規内容の確認
= form_with model: @task, local: true do |f|
table.table.table-hover
tbody
tr
th= Task.human_attribute_name(:name)
td= @task.name
=f.hidden_field :description
tr
th= Task.human_attribute_name(:description)
td= simple_format(@task.description)
=f.hidden_field :description
=f.submit '戻る', name: 'back', class: 'btn btn-secondary mr-3'
=f.submit '登録', class: 'btn btn-primary'
7-1-3 登録アクションで「戻る」ボタンからの遷移に対応する。
上記の確認画面のビューには戻るボタンと登録ボタンの2つがある。戻るボタンを機能させようと思ったらこの二つのボタンのどちらが押されているかの判断をする必要がある。そのために戻るボタンにはname属性にbackをつけた。プログラミング上ではもしname属性のbackが押されたら元に戻るという操作になる。
つまりparams[:back]の結果が出れば良い。
params[:back]が押されると元に戻るという動作をcreateアクションに書けば良い
def create
@task = current_user.tasks.new(task_params)
if params[:back].present? #present?は値がある場合trueとなる真偽値
render :new
return
end
真偽値で使うメソッドの種類
メソッド名 | メソッドの意味 |
---|---|
nil? | 変数の値がnil、または値がないときにtrueになる |
empty? | 変数の値が""(文字列の場合)や値が空白の場合、真となります。nil?との違いは、empty?は変数の値はあることはあるが、その値が空を示しているところ |
blank? | 値と言えるものがない場合にtrueとなる |
present? | 値と言えるものがある場合はtrueとなる |
7-2 一覧画面に検索機能を追加する
タスク一覧にあるタスクの数が多くなってくるといちいち探し出すのがめんどくさくなってくる。そんな時に検索機能があった方が便利だろう。
検索機能をつけるにはRansackというgemを使う
7-2-2 名称による検索
Ransackを使って検索機能を追加する
def index
@q = current_user.task.ransack(params[:q])
@task = @q.result(distinct: true).recent
end
@q = current_user.task.ransack(params[:q])
ransackではquery parameter(params[:q])を取って検索をかける
ログイン中のユーザーのtaskをransackで検索しそれを@qと置いている
@task = @q.result(distinct: true).recent
検索で出た@qを
重複する検索結果を除外しつつ(result(distinct: true))
登録日時の並びで表示する(recent)
ransackが実装できたので実際にビューで検索できるようにしてみる
検索機能の追加にはsearch_form_forを使う
h1 タスク一覧
= search_form_for @q, class: 'mr-5' do |f|
.form_group.row
=f.label :name_cont, '名称', class: 'col-sm-2 col-form-label'
.col-sm-10
=f.search_field :name_cont, class: 'form-control'
.form-group.row
=f.label :created_at_gteq, '登録日時', class: 'col-sm-2 col-form-label'
.col-sm-10
= f.search_field :created_at_gteq, class: 'form-control'
.form-group
=f.submit class: 'btn btn-outline-primary'
= link_to '新規登録', new_task_path, class: 'btn btn-primary mb-3'
name_cont:nameと部分一致している物を選ぶ。
.search_field:記入場所
created_at_gteq:記入した投稿日時より大きい(未来:gteq)の投稿を選ぶ
7-3 一覧画面にソート機能を追加する
def index
@q = current_user.task.ransack(params[:q])
@task = @q.result(distinct: true).recent
end
recentでソートをしていたが次は任意の順番でソートをする
まずresentをとる
def index
@q = current_user.task.ransack(params[:q])
@task = @q.result(distinct: true)
end
table.table.table-hover
thead.thead-default
tr
th= sort_link(@q, :name, default_order: :desc)
th= Task.human_attribute_name(:created_at)
th
sort_linkをつけるとソート操作ができるようになる
第一引数にはransackによって得られた値(ここでは@q)
第二引数にはソートを行う対象のカラム(ここではname)
default_order: :desc
7-4 メールを送る
Railsはメールを送るためにメイラーという仕組みを利用している。メイラーを使いメールを作成・送信する。
メイラーはメイラーファイルに記述する
class TaskMailer < ApplicationMailer
def creation_email(task)
@task = task
mail(
subject: 'タスク作成完了メール'
to: 'user@example'
from: 'taskleaf@example'
)
end
end
subjectやto、fromといった情報のmailをcreation_emailメソッドとしておく
7-4-3 メールの送信処理
実際にメールを送信できるようにしていく
def create
@task = current_user.tasks.new(task_params)
if params[:back].present?
render :new
return
end
if @task.save
TaskMailer.creation_email(@task).deliver_now
redirect_to @task, notice: "タスク「#{@task.name}」を登録しました"
else
render :new
end
end
上記のようにTaskMailer.creation_email(@task).deliver_nowをつけると@taskについてのメールが送信される。deliver_nowは即時送信を行うためのメソッド。他にもdeliver_laterメソッドも存在している
7-5 ファイルをアップロードしてモデルに添付する
Active Storageというファイル管理gemが出てきて、それらを使って写真や画像を添付する
実際に添付するには以下の方法で添付する
class Task < ApplicationRecord
has_one_attached :image
....
end
has_one_attachedメソッドを使うことによって1つのタスクに1つの画像(image)を紐付けることが可能になる。
...
...
...
.form-group
=f.label :image
=f.file_field :image, class: 'form-control'
...
end
ja.ymlにも「image:画像」と設定しておく
task_paramsメソッドのpermitもimageも許可しておく
確認画面にも表示されるようにコードを書く
...
tr
th= Task.human_attribute_name(:image)
td= image_tag @task.image if @task.image.attached?
tr
...
...
...
if @task.image.attached?は画像が添付されているかどうかを表す。
実際に画像があればimage_tagで表示する
7-7 ページネーション
タスクが多くなればなるほど今までやっていた情報を全て表示する方法では動作が重たくなってきてしまう。ページネーションは一定数以上のファイル数になればそれ以上の表示は次のページへ渡すなどをし、ページによって情報を分散させ動作を軽くする方法。
このページネーションにはkaminariというgemファイルが用いられる。
元々のtasks_controllerファイルを
def index
@q = current_user.task.ransack(params[:q])
@task = @q.result(distinct: true)
end
.page(params[:page])を後ろにつけることによって1ページあたりに表示する件数を決めることができる(デフォルトで1ページ25件)
def index
@q = current_user.task.ransack(params[:q])
@task = @q.result(distinct: true).page(params[:page])
end
次に実際にビューファイルに反映されるようにする
.mb-3
=paginate @tasks
=page_entries_info @tasks
...
...
...
paginateヘルパーメソッドとpage_entries_infoヘルパーメソッドを使うことによって自動的に作成してくれる。
7-8 非同期処理や定期実行を行う(Jobスケジューリング)
Railsではバックグラウンドで様々な処理を非同期に行うためのActive Jobというフレームワークが用意されている。ActiveJobは以下の時に使われる
・処理が重たくユーザーを待たせてしまっている
・指定した日時にアクションを起こしてほしい
そんな時に使うのがsidekiqという仕組みである
①まずRailsとsideskiqを同期する
config.active_job.queue_adapter = :sideskiq
②app/jobs/sample_job.rbを作りperformメソッドを作る
class SampleJob < ApplicationJob
queue_as :deault
def perform(*args)
Sidekiq::Logging.logger.info "サンプルジョブを実行しました"
end
end
performメソッドを呼び出して処理する
def create
@task = current_user.tasks.new(task_params)
...
if @task.save
TaskMailer.created_email(@task).deliver_now
SampleJob.perform_later
...
...
...
SampleJob.perform_laterが非同期処理を行うようになる
7-8-3 実行日時指定
setメソッドを使うと日時を指定して処理を実行できるようになる
# 翌日の正午に実行
SampleJob.set(wait_until: Date.tomorrow.noon).perform_later
# 1週間後に実行
SampleJob.set(wait: 1.week).perform_later