1.バージョンを確認しましょう!
Rails 5.1.6
ruby 2.7.2p112
2.完成イメージ
投稿に制限時間を設定し、何かしらの処理をつける機能です。
今回は 「投稿(タスク)を設定し、制限時間を超えると通知が来る機能」 を実装する準備段階です。
3.実装の大きな流れ
1.投稿モデル(Tweet)に、制限時間を保存するカラムを追加する。
2.投稿を保存するときに、制限時間と現在時刻を比較して、制限時間が過ぎていないかをチェックするアルゴリズムを記入する。
3.制限時間が過ぎている場合はエラーを返し、投稿を保存しない設定を仕込む。
ちなみに本記事はこのような目次で進んで行きます!
一緒に楽しんでいきましょう ᕙ( ˙꒳˙ )ᕗ
4. モデルに、制限時間を保存するカラムを追加しよう。
$ rails generate migration AddLimitTimeToTweets limit_time:datetime
$ rails db:migrate
tweetsテーブルに、limit_timeというカラムを追加しました。
データ型は日時の保存に適しているdatetime型を採用しています。
多分マイグレーションファイルはこんな感じ。(一例)
class AddLimitTimeToTweets < ActiveRecord::Migration[6.1]
def change
add_column :tweets, :limit_time, :datetime
end
end
5.アルゴリズムを仕込む。
制限時間についてのアルゴリズムを仕込みましょう。
この記述がないと、現在時間よりも以前の時間で制限を設けることができ、サイトとして破綻してしまいます。
下記のモデルをこんな感じで編集していきましょう ᕙ( ˙꒳˙ )ᕗ
class Tweet < ApplicationRecord
#追加
validate :check_limit_time, on: :create
validate :check_limit_time, on: :update
private
def check_limit_time
if limit_time.present? && limit_time < Time.now
errors.add(:limit_time, "制限時間を過ぎています")
end
end
end
コードの確認を初めます。先にprivate
の中身から。
1) if limit_time.present? && limit_time < Time.now
の説明
まずcheck_limit_time
というメソッドを作っています。これはどんな処理でしょうか。
if A && B
は、AかつBの条件が成り立つ際に処理を実行しますという条件分岐文です。
この場合、Aはlimit_time.present?
ですね。
これは、limit_time
という変数が存在するかどうかを確認するコードです。
Bは、limit_time < Time.now
です。
今の時間よりも、以前の場合ということですね。
つまり、現在は1月23日10:00なのに、1月23日8:00に制限を設定してしまったというようなイメージです。
論理的に破綻していますね。
2) errors.add(:limit_time, "制限時間を過ぎています")
の説明
このような場合には、 errors.add(:limit_time, "制限時間を過ぎています")
という処理を実行します。これは「制限時間を過ぎています」という警告を表示するコードですね。
3) validates
の説明
Validatesは、データベースに保存する前に、入力されたデータが正しいかどうかをチェックする機能です。
例えば、以下のように、emailカラムが必須であることをチェックする検証を追加することができます。
class User < ApplicationRecord
validates :email, presence: true
end
validationによって入力されたデータが正しくない場合は、保存されず、エラーを返すことができます。よって、データベースに不正なデータが保存されないようにすることができ、アプリケーションの信頼性を高めることができます。
今回は「投稿作成時」と、「投稿更新時」に確認を行いたいので、それぞれにcreateとupdateを仕込んでいます。
6.制限時間と現在時刻を比較して、タイムリミットを表示させる。
Viewファイルに下記のコードを追加しましょう✊
<% if @tweet.limit_time.present? && @tweet.limit_time > Time.now %>
<div class="timer">
<%= distance_of_time_in_words(@tweet.limit_time, Time.now) %>
</div>
<% end %>
ここでのif文は先ほどと同様のものです。割愛しますね。
ここではdistance_of_time_in_words
というメソッドを使っています。
これは第一引数(@tweet.limit_time
)と、
第二引数(Time.now
)の時刻の間隔を、「xx分前」や「yy時間前」といった文字列に変換するものです。
ここで計算が行われることで、◯◯分前という表示を出すことに成功しました。
7.まとめ
そこまで複雑な機能設計はないので、もっと複雑なものを実装次第Qiitaに取り入れようと思っております。
タイマーかっこいい感じで表示したいなあ。少しがんばります。