Rails应用每24小时自动切换图片:实例变量传递及调度方案咨询
解决方案
核心问题分析
你当前的思路存在逻辑误区:如果在控制器中调用rake任务,确实会在每次请求时都执行切换逻辑,完全达不到“每24小时自动切换”的目的。正确的做法应该是把「每日选图标记」的逻辑交给后台定时任务执行,控制器只负责「读取已选好的当日图片」。
重构方案:用模型类方法实现逻辑复用
我们可以将选图、标记的逻辑抽离到Newspaper模型的类方法中,既方便定时任务调用,也能让控制器直接读取结果,同时解决6张图片循环展示的问题。
1. 重构Newspaper模型
class Newspaper < ApplicationRecord # 筛选未被标记为已展示的图片 scope :undone, -> { where(done: false) } # 选择当日展示图片并标记为已展示,自动循环重置 def self.select_todays_paper paper = undone.first return unless paper paper.update(done: true) # 当所有图片都被标记过,重置状态实现循环展示 update_all(done: false) if undone.empty? paper end # 获取当前正在展示的图片(最近被标记的) def self.current_paper order(updated_at: :desc).find_by(done: true) end end
2. 简化定时任务(rake/Sidekiq)
修改原rake任务,直接调用模型类方法:
namespace :images do desc "每日自动选择展示的图片" task select_today: :environment do Newspaper.select_todays_paper end end
用Whenever配置每日定时执行(比如凌晨0点):
# config/schedule.rb every 1.day, at: '00:00' do rake 'images:select_today' end
3. 控制器读取当日图片
控制器只需要调用current_paper获取已选好的图片,无需执行切换逻辑:
class GalleriesController < ApplicationController def index @todays_paper = Newspaper.current_paper # 首次运行时如果还没有当日图片,手动触发一次选图 @todays_paper ||= Newspaper.select_todays_paper end end
为什么这样做?
- 定时任务每日仅执行一次选图标记,避免了每次请求重复执行逻辑
- 控制器只做读取操作,性能更优,职责更清晰
- 模型类方法统一了逻辑,避免代码重复
- 新增了循环重置逻辑,解决6张图片全部展示后无图可选的问题
内容的提问来源于stack exchange,提问作者Tom Kitson
相关产品推荐
相关产品推荐

