0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Rails学習 3日目その2

Posted at

Ruby on Rails5速習実践ガイド chapter7

7-1 登録や編集の実行前に確認画面をはさむ

登録する前に確認画面が出てきてそこで確認してからデータが登録されるように設定する。
まずは確認画面が表示されるアクション(conform_newアクション)をコントローラーに書く

app/controller/tasks_controller.rb
 def confirm_new
   @task = current_user.tasks.new(task_params)
   render :new unless @task.valid? #もしデータベースに@taskがなかったら実行

その次にルーティングを記入

config/routes.rb
resources :tasks do
  post :confirm, action: :confirm_new, on: :new
end

post :confirm, action: :confirm_new, on: :new
この部分は元々以下の形であった

config/routes.rb
resources :tasks do
  new do
   post :confirm, action: :confirm_new
  end
end

newブロック内に要素が一つだけの場合は後ろにon: :ブロック名とすることでルーティングがかける

次に確認画面のビューを作る

app/views/tasks/confirm_new.html.slim
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アクションに書けば良い

app/controllers/tasks_controller.rb
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を使って検索機能を追加する

app/controllers/tasks_controller.rb
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を使う

app/views/tasks/index.html.slim
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 一覧画面にソート機能を追加する

app/controllers/tasks_controller.rb
def index
  @q = current_user.task.ransack(params[:q])
  @task = @q.result(distinct: true).recent
end

recentでソートをしていたが次は任意の順番でソートをする
まずresentをとる

app/controllers/tasks_controller.rb
def index
  @q = current_user.task.ransack(params[:q])
  @task = @q.result(distinct: true)
end
app/views/tasks/index.html.slim
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はメールを送るためにメイラーという仕組みを利用している。メイラーを使いメールを作成・送信する。
メイラーはメイラーファイルに記述する

app/mailers/task_mailer.rd
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 メールの送信処理

実際にメールを送信できるようにしていく

app/controllers/tasks_controller.rb
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が出てきて、それらを使って写真や画像を添付する
実際に添付するには以下の方法で添付する

app/models/task.rb
class Task < ApplicationRecord
  has_one_attached :image
....

end

has_one_attachedメソッドを使うことによって1つのタスクに1つの画像(image)を紐付けることが可能になる。

app/views/tasks/_form.html.slim
...
...
...
.form-group
  =f.label :image
  =f.file_field :image, class: 'form-control'
...
end

ja.ymlにも「image:画像」と設定しておく
task_paramsメソッドのpermitもimageも許可しておく

確認画面にも表示されるようにコードを書く

app/views/tasks/show.html.slim
...
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ファイルを

app/controllers/tasks_controller.rb
def index
  @q = current_user.task.ransack(params[:q])
  @task = @q.result(distinct: true)
end

.page(params[:page])を後ろにつけることによって1ページあたりに表示する件数を決めることができる(デフォルトで1ページ25件)

app/controllers/tasks_controller.rb
def index
  @q = current_user.task.ransack(params[:q])
  @task = @q.result(distinct: true).page(params[:page])
end

次に実際にビューファイルに反映されるようにする

app/views/tasks/index.html.slim
.mb-3
  =paginate @tasks
  =page_entries_info @tasks
...
...
...

paginateヘルパーメソッドとpage_entries_infoヘルパーメソッドを使うことによって自動的に作成してくれる。

7-8 非同期処理や定期実行を行う(Jobスケジューリング)

Railsではバックグラウンドで様々な処理を非同期に行うためのActive Jobというフレームワークが用意されている。ActiveJobは以下の時に使われる

・処理が重たくユーザーを待たせてしまっている
・指定した日時にアクションを起こしてほしい

そんな時に使うのがsidekiqという仕組みである

①まずRailsとsideskiqを同期する

config/environments/development.rb
config.active_job.queue_adapter = :sideskiq

②app/jobs/sample_job.rbを作りperformメソッドを作る

app/jobs/sample_job.rb
class SampleJob < ApplicationJob
  queue_as :deault

  def perform(*args)
    Sidekiq::Logging.logger.info "サンプルジョブを実行しました"
  end
end

performメソッドを呼び出して処理する

app/controller/tasks_controller.rb
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
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?