Rake + Wheneverでブログのステータスを自動的に変更するアプリを作成

# 目的
シンプルなブログアプリに記事のステータスをcronタスクにて自動的に変更する機能を実装する。
# 新規の技術・機能の概要
**Rake**
Rubyで記述されたビルドツール
**Whenever**
railsにてcronタスクを簡単に設定するgem
**執筆時の対象Version**
Rails:5.2.6
Whenever:1.0.0
# 実装方法
## セットアップ ##
```terminal:terminal
# アプリの新規作成
rails new blog_sample
cd blog_sample
```
```terminal:terminal
# scaffoldにてBlogモデルを生成
rails g scaffold Blog title:string content:text
```
```diff ruby:db/migrate/*******_create_blogs.rb
class CreateBlogs < ActiveRecord::Migration[5.2]
  def change
    create_table :blogs do |t|
      t.string :title
      t.text :content
      # マイグレーションファイルに記事のステータスを追記
+     t.integer :state, default: 0, null: false
      t.timestamps
    end
  end
end
```
```termina:ternimal
# DBを生成
rails db:create
# マイグレーションを実行
rails db:migrate
```
```diff ruby:config/routes.rb
Rails.application.routes.draw do
# root_pathを設定
+ root to: 'blogs#index'
  resources :blogs
end
```
## 記事ステータスの設定 ##
Blogのmodelとviewの設定を行います。
```diff ruby:app/models/blog.rb
class Blog < ApplicationRecord
  # 記事ステータスを設定
+ enum state: { draft: 0, published: 1, publish_wait: 2}
end
``` 
```diff ruby:app/views/blogs/index.html.erb
---省略---
  <tbody>
    <% @blogs.each do |blog| %>
      <tr>
        <td><%= blog.title %></td>
        <td><%= blog.content %></td>
	#　記事ステータスを表示
+       <td><%= blog.state %></td>
        <td><%= link_to 'Show', blog %></td>
        <td><%= link_to 'Edit', edit_blog_path(blog) %></td>
        <td><%= link_to 'Destroy', blog, method: :delete, data: { confirm: 'Are you sure?' } %></td>
      </tr>
    <% end %>
---省略---
```
```diff ruby:app/views/blogs/show.html.erb
 <p>
   <strong>Title:</strong>
   <%= @blog.title %>
 </p>

 <p>
   <strong>Content:</strong>
   <%= @blog.content %>
 </p>
#　記事ステータスを表示
+ <p>
+ <strong>State:</strong>
+ <%= @blog.state %>
+ </p>
---省略---
```
```diff ruby:app/views/blogs/_form.html.erb
---省略---
  <div class="field">
    <%= form.label :title %>
    <%= form.text_field :title %>
  </div>

  <div class="field">
    <%= form.label :content %>
    <%= form.text_area :content %>
  </div>
 # 記事ステータスを入力
+ <div class="field">
+   <%= form.label :state %>
+   <%= form.select :state, Blog.states.keys.to_a, {} %>
+ </div>

  <div class="actions">
    <%= form.submit %>
  </div>
 <% end %>
```   
## 記事ステータスを変更するRakeタスクを設定 ##
```terminal:terminal
# Rakeタスク「change_state」を作成
rails g task change_state
```
```diff ruby:lib/tasks/change_state.rake
 # 下記を追記　記事ステータスがpublish_wait:2の記事をpublished:1へ変更する
 namespace :change_state do
+  desc "Blogのstateを変更"
+  task :change_published => :environment do
+    Blog.where(state:2).find_each do |blog|
+      blog.published!
+    end
+  end
 end
```
```terminal:terminal
# 下記のコマンドを実行、ズラズラと出力結果が表示される。
rake -vT
（省略）
rake change_state:change_published      # Blogのstateを変更
（省略）
# 下記のコマンドを実行するとrakeタスクが実施される
rake change_state:change_published
```
## wheneverの導入 ##
```diff ruby:gemfile
 # 下記をGemfileに追記
+ gem 'whenever'
``` 
```terminal:terminal
# gemのインストール
bundle install
# wheneverの初期化
bundle exec wheneverize .
```
```diff ruby:config/schedule.rb
 # ファイルが生成されるので、下記を設定する
+ require File.expand_path(File.dirname(__FILE__) + '/environment')
+ rails_env = ENV['RAILS_ENV'] || :development
 # cronを実行する環境変数をセット
+ set :environment, rails_env
 # cronのログの吐き出し場所
+ set :output, "#{Rails.root}/log/cron.log"

 # 10分ごとにrakeタスクを実行する
+ every 10.minutes do
+ rake 'change_state:change_published'
+ end
```
    
## cronへ設定反映 ##
```terminal:terminal
# 設定を反映
bundle exec whenever
# cronタスクを確認
crontab -l
# 編集した設定を反映
bundle exec whenever --update-crontab
# cronからタスクを削除
bundle exec whenever --clear-crontab
```

# 参考サイト・資料
[Udemyメディア：Rails scaffoldを初心者向けに解説！実際にアプリを作ってみよう！](https://udemy.benesse.co.jp/development/system/scaffold.html)
[Qiita:Railsでwheneverを使ってcronを設定する](https://qiita.com/Esfahan/items/e7a924f7078faf3294f2)
[Github:Whenever](https://github.com/javan/whenever)