『Rails』コールバックを使って公開記事と下書き記事の投稿日更新してみた

2019/09/07◉ 3 views


何故コールバックを使ったのか?


まず今回何故コールバックを使ったのか説明します。

実は開発時には気づけなかったのですが、下書き記事を1日に作成したとします。

下書きも終わり4日目に公開したとします。

そしたら公開日が普通なら4日になりますよね?

それがなんと1日に公開になってるではありませんかー!!!!

1ヶ月前に下書きを作成して書き溜めしてても、公開日が1ヶ月も前だったら、ブログ一覧に1ヶ月前の日付で表示されちゃうんですw

埋れます!!!過去の記事になっちゃう!!

こりゃあかーんってなったわけですよ!

なのでそこの修正を今回考えました。

ブログ一覧の記事の順番


このブログの記事一覧は最初

@blogs = Blog.published.order("created_at DESC").page(params[:page]).per(10)

このようになってました。

公開記事をcreated_atの降順で表示させてます。下書き記事を作成した日がcreated_atになってます。

だから過去に作成した下書きの日付のまま、公開になっちゃうんですね....

なので自分なりに考えた結果、created_atを公開した時の時間で上書きしちゃうでした。

下書きから公開に更新するここの切り替え時にcreated_atを上書き。

こう考えたんですね!

それを僕がお世話になっているコミュニティの分報で呟いてたら、ありがたいことに助言してくださったのです。

こちら
にゅ〜ぶる会


せっかく助言もらえたのでこれでやってみることにしました!
にゅ〜ぶるさん
ぬぬぬさん
ありがとうございます!

はて....コールバック....どっかで少し勉強した気がするが...

全然覚えてねええええええ!!!!

超ググりましたよ!!!!!


 コールバックって何?



コールバックは、オブジェクトのライフサイクル期間における特定の瞬間に呼び出されるメソッド

Active Recordオブジェクトが作成/保存/更新/削除/検証/データベースからの読み込み、

などのイベント発生時に常に実行されるコードを書くことができる。

例えばよく使うものだとこの辺りですね
  • create
  • destroy
  • save
  • update

参考記事は
こちら
こちら

コールバックにもいっぱい種類があってその中で今回僕がチョイスしたのがこちら

オブジェクトの作成


  • before_create

オブジェクトがDBに新規保存(INSERT)される直前で実行されます

オブジェクトの更新


  • before_update

オブジェクトにより、DBを更新(UPDATE)する直前で実行されます。

この2つを使ってコードを追加していこうと思います!


コールバックを使って機能を修正してみる



まずはblogsテーブルに日時カラムを追加します。

bin/rails g migration AddTimeToBlogs time:datetime

timeカラムの追加をしdatetime型にします。

DateTime型 ( = 曜日 + 日付 + 時刻 )

お決まりの

bin/rails db:migrate

これでカラムの追加はできました。
timeカラム


コールバックはmodelに書いていきます。
ちなみにenumを使ってます。

enumの記事はこちら
enum status: { draft: 0, published: 1 }

/models/blog.rb
class Blog < ApplicationRecord

before_create :time_create

before_update :time_update

そしてここから条件を考えていきます。
 private   プライベートの中に条件書くよ

def time_create
end

def update_create 
end

まずはtime_create


公開記事を新規作成した時や下書き記事を新規で作った状態の時。

if self.published?
selfをつけるとクラスメソッドになります。
なのでこれはblog.published?ってことになります。
published?は公開記事だったらtrueになります。
よーするに、もし公開記事だったら〜って意味ですね。
self.time = Time.zone.now
timeカラムにTime.zone.nowを代入します。
Time.zone.nowはActiveSupport::TimeWithZoneクラス
rails独自のクラスで、Timeクラスと完全な互換性がある。
ざっくりと説明すると現在の時間を習得できます。

これをまとめるとこうなります。
def time_create
    if self.published?
      self.time = Time.zone.now
    end
end

draft(下書き時は)作成時は、何も条件書いてないのでtimeにはnilが入るようになってます。

published(公開記事)作成時はtimeには、現在の時間が入るようになりました。

お次はtime_update


if self.status_changed?(from: "draft", to:"published")
self.status_changed?
これはblog.statusの要素が変更されたか確認できるメソッドになります。

(from: "draft", to:"published")ここで要素を指定してあげるんですね!

よーするに
もしstatusカラムがdraftからpublishedに変更されたらって意味ですね。

self.time = Time.zone.now
先ほどの説明と一緒です。

現在時間をここで入れてあげます

elsif self.status_changed?(from: "published", to:"draft")
ここでelsifにして条件2を書いてきます。

elseにしてしまうと思った条件とは違くなるので注意でした。

ここでは
もしstatusカラムがpublishedからdraftに変更されたらって意味ですね。

self.time = nil
timeにnilを入れてあげます。

ここは悩んだのですが下書きに戻したらnilにすることにしました。
これをまとめるとこうなります。

def time_update
    if self.status_changed?(from: "draft", to:"published")
      self.time = Time.zone.now
    elsif self.status_changed?(from: "published", to:"draft")
      self.time = nil
    end
end

これでどうなるのか?


  • 新規作成(下書き) nil
  • 新規作成(公開記事)公開日時
  • 下書きから公開記事に編集 公開日時
  • 公開記事から公開記事の編集 公開日時のまま
  • 公開記事から下書きに編集 nil
  • 下書きから下書きの編集 nil

このようにできるようになり、やりたかった事がちゃんとできるようになってます。

あとはブログ一覧ページのソートを変えてあげます。

@blogs = Blog.published.order(time: "DESC").page(params[:page]).per(10)

timeカラムの降順にしました。

timeカラムには公開日時が入っているのでその降順ですね!!

忘れないようにここも変えときます。

blog.time.strftime("%Y/%m/%d")

2019/08/19の部分ですね!

前はここがcreated_atにしてましたので。
日付




これでコールバックによるコードの修正が完了しました!

1日中悩んでググったり条件考えたりして自分なりに作ってみました。

助言がなかったらコールバックなんて絶対使ってなかったと思います。

まだこの程度のコードしか作れないけど、ものすごく勉強になりました。

コールバック...この先も必ず使用するだろうし、少し触れて本当によかったと思います!

問題が1つだけ発生



このままデプロイしたらerrorでサイトが開けなくなりましたwww

既存の公開記事のtimeカラムに何も入ってない状態になってるからかな?

 ターミナルで
bin/rails c -e production 

全部で4記事公開してたので1つ1つこれで解決させました....w
 
blog=Blog.find(15) 
 
blog.time=blog.created_at 

blog.save 

荒技!!!!!!!!

これで無事サイトが見れるようになりましたw

ふう....よかった....。


これで心置きなく下書きが書けます。

次回

タグ機能を追加してみた


9月8日追記タグ機能実装してたのですが、rails6になりエラーが出てるようで実装に時間がかかりそうです。

記事は実装完了次第、書いていこうと思います。

なので次回はgoogle AdSenseのお話をちょろっとしようと思います。


まだまだちょめこのブログサイトはパワーアップしますよ〜

どんどん機能追加して進化させるんで、優しい目で見守って応援して助言くださいwww

ここまで読んでいただいてありがとうございました!!

また来てください。

ばいちゃ!!!





このブログサイトは初学者の僕が独学で
Ruby on Railsで作ったブログサイトです。 間違っている所もあるかもしれません。 あくまで参考程度にしていただけたらなと思います。 何かありましたらお問い合わせか、Twitter@ちょめこよりご連絡下さい。