Ruby on Rails能否基于date属性而非created_at销毁对象?
基于自定义
date属性实现Event对象的定时销毁 当然可以基于自定义的date属性来完成这个销毁操作,完全不需要局限于created_at!你的业务逻辑是围绕活动举办日期展开的,用date属性来触发销毁完全合理,下面一步步帮你调整实现:
第一步:将date字段转为datetime类型
目前你的date是字符串类型,这会导致时间比较逻辑出错,先把它转成datetime类型:
- 生成迁移文件:
rails generate migration ChangeDateToDatetimeInEvents - 打开生成的迁移文件,修改内容为:
class ChangeDateToDatetimeInEvents < ActiveRecord::Migration[7.0] def change change_column :events, :date, :datetime end end - 运行迁移:
rails db:migrate
之后确保在代码中给date属性赋值时,使用datetime对象而非字符串(比如event.date = DateTime.parse("2024-05-20 10:00"))。
第二步:修正rake任务的查询条件
你当前的rake任务条件写反了——现在的逻辑是销毁date早于12小时前的活动,但你需要的是活动举办日期过后12小时才销毁,也就是当当前时间超过date + 12小时时执行销毁。修正后的rake任务:
namespace :events do desc "Delete events 12 hours after their scheduled date" task delete_12_hours_post_date: :environment do # 筛选出举办日期距离当前时间已超过12小时的活动 Event.where('date <= ?', Time.current - 12.hours).destroy_all end end
如果想让SQL条件更直观,也可以用数据库原生的时间运算(兼容多数主流数据库):
Event.where('date + INTERVAL 12 HOUR < ?', Time.current).destroy_all
第三步:添加销毁时的邮件触发逻辑
在Event模型中添加销毁回调,触发对应的邮件:
class Event < ApplicationRecord # 假设你有关联的参与者和未参与者方法 has_many :participations has_many :participants, through: :participations, source: :user after_destroy :send_post_event_emails private def send_post_event_emails # 给参与者发送致谢邮件 participants.each do |participant| EventMailer.thank_you_email(participant, self).deliver_later end # 给未参与者发送致歉邮件(这里需要你根据业务逻辑定义未参与者的筛选方式) User.where.not(id: participants.pluck(:id)).each do |non_participant| EventMailer.apology_email(non_participant, self).deliver_later end end end
注意:destroy_all会逐个触发每个Event对象的after_destroy回调,所以邮件会正确发送。
最后:配置定时任务
为了让这个rake任务自动定期执行,推荐用whenever gem来配置cron:
- 添加gem到Gemfile:
gem 'whenever', require: false - 生成配置文件:
bundle exec wheneverize . - 打开
config/schedule.rb,添加任务:every 1.hour do rake "events:delete_12_hours_post_date" end - 更新crontab:
bundle exec whenever --update-crontab
这样你的活动就会在举办日期过后12小时被自动销毁,同时触发对应的邮件通知啦!
内容的提问来源于stack exchange,提问作者Matt Croak
相关产品推荐
相关产品推荐

