[Rails] Status update using Rake task

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.

What is a Rake task in the first place?

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.

Creating and implementing Rake tasks

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.

Introducing whenever

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'

cron update

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.

List of referenced pages

[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

[Rails] Status update using Rake task
[Rails] Implement rake task
rails learning rake task, cron, whenever
Rails: How to write a rake task nicely
Prevent operations! How to securely update Rails manually using transactions
About regular execution of rake task of rails application on heroku
[Rails] I tried to implement batch processing with Rake task
Search function using [rails] ransack
Try using view_component with rails
[Rails] Save images using carrierwave
Japaneseize using i18n with Rails
[Rails] Japanese localization using rails-i18n
Let's define a Rake task.
[Rails] Test code using Rspec
Ajax bookmark function using Rails
Error when using rails capybara
[Rails] Try using Faraday middleware
Detailed tips when using Rails
[Rails 6] Star-shaped review using Raty.js