Ruby on rails学习:cms里的文章定时发布功能实现-whenever实现

利用whenever实现一个cms的posts定时发布功能
更新于: 2022-03-19 13:08:33

原理

  1. 定时任务,每分钟运行一次
  2. post.rb 里定制实现 Post.publish! 方法
  3. 查找 published_at 小于当前时间的 post 列表
  4. 根据3的结果,修改文章状态 draft → published
  5. 前端只显示 published 的文章
  6. time_zone 的配置

初始化一个 config/schedule.rb

dir = File.expand_path("..", __dir__)
set :output, "#{dir}/log/schedule.log"

# 定时发布任务
every 1.minute do
  rake 'posts:publish', :environment => ENV['RAILS_ENV'] || 'development'
end

实现相关的 post.rb

  • 文章分为 :draft/:published 两种状态(以后可以扩展 deleted 等状态)
  • 发布,实际上只是修改状态(:draft → :published)
  • 对于 Post.publish! 方法,实际上是扫描所有可发布的,进行发布
  • 这里注意 time_zone 的配置
class Post < ApplicationRecord
  # status: 已经发布/草稿状态
  enum status: [:published, :draft]
  validates_uniqueness_of :title
  validates_presence_of :title

  # filters
  scope :by_status, -> (status) { where status: status }
  scope :draft, -> { where(status: :draft) }
  scope :published, -> { where(status: :published) }
  scope :ready_for_publish, -> { where('published_at <= ?', Time.now) }

  def publish_now!
    self.status = :published
    save!
  end

  def self.publish!
    Post.draft.ready_for_publish.find_each do |post|
      post.publish_now!
    end
  end
end

railstime_zone 的配置

位置在这里 ./config/application.rb

# timezone
config.time_zone = "Beijing";
config.active_record.default_timezone = "Beijing";

总结

  • 优点: 简单,只依赖于系统的 crontab 服务
  • 缺点: 不适合特别精确的场景

参考