In this article, we will first add a new status of "waiting for publication" to the blog app that has two types of article statuses, "public" and "draft". Then, if the scheduled publication date and time of the article saved in the "waiting for publication" status is earlier than the current date and time, the batch will be automatically rotated and updated to the "publication" status.
I will write about how to create a Rake task that enables the above update and also run that process using whenever.
Rake is a simple build tool that allows you to describe the processing contents in Ruby. The processing content written in Ruby is called Rake task and can be executed by defining it in Rakefile.
A file will be created in lib / tasks by typing $ rails generate task task name
.
$ rails generate task status_task
Enter the process you want to execute in article.rb and the created file.
article.rb
enum state: { draft: 0, published: 1, publish_wait: 2 }
scope :past_published, -> { where('published_at <= ?', Time.current) }
Added publish_wait of "waiting for publication" because originally defined only two types of enums, "draft" and "public" in article.rb. In scope, the range of past_published is defined as the date and time of publication in the past from the current time.
status_task.rake
namespace :status_task do
desc 'If there is a waiting list whose publication date and time is in the past, the status will be changed to "public".'
task update_status_task: :environment do
Article.publish_wait.past_published.find_each(&:published!)
end
end
Get the article "waiting for publication" with Article.publish_wait, and update the status of past_published to "published" with published !. In find_each, by default, 1000 records are acquired and the acquired data is processed one by one, so the processing execution speed is less likely to slow down compared to find, which processes after acquiring all the data.
Next, we will introduce whenever to execute the Rake task created so far every hour. whenever is a library prepared in rails for managing the processing time of regular execution batches, and originally it is necessary to prepare a process called cron that "executes XX at XX time". If you use, whenever, you can write the contents to be described in crontab that gives instructions to cron in ruby language.
This allows you to set the Rake task to run every hour.
First of all, I will write from the introduction method.
gem 'whenever'
If you do bundle install and execute the following, a file called cofig / schedule.rb will be created.
$bundle exec wheneverize .
In this schedule.rb, write the process to run the Rake task every hour.
config/schedule.rb
# Rails.Required to use root
require File.expand_path(File.dirname(__FILE__) + "/environment")
#Environment variables that run cron
rails_env = ENV['RAILS_ENV'] || :development
#Set environment variables to run cron
set :environment, rails_env
#Location of cron log spit
set :output, "#{Rails.root}/log/cron.log"
#Run rake task every hour
every :hour do
rake 'article_state:update_article_state'
end
Make it possible to set the publication date and time only every hour.
app/assets/javascripts/admin.js
format: 'YYYY-MM-DD HH:00'
Before reflecting the settings written in schedule.rb, first check the updated contents without rewriting cron.
$ bundle exec whenever
If there is no problem with the settings, update crontab below.
$ bundle exec whenever --update-crontab
Check if the Rake task can be executed without any problem with the following command.
$ rake status_task:update_status_task
That's it.
[Ruby 2.7.0 Reference Manual / Library List / Rake Library] https://docs.ruby-lang.org/ja/latest/library/rake.html
[Rails document find_each] https://railsdoc.com/page/find_each
[If you want to update a large amount of data in a batch with Rails, use find_each] http://blog.livedoor.jp/sasata299/archives/51882704.html
[How to specify Rails whenever] https://taker.hatenablog.com/entry/2019/12/02/195950
Recommended Posts