How do I change the images in a rails app every 24 hours?

66 views Asked by At

I have an Rails app with a gallery of 6 images. I would like to automatically switch which images are displayed every 24 hours. I have the logic for selecting the images in a rake task, which returns an instance variable of @todays_paper:

namespace :images do
  desc "TODO"
  task next_batch: :environment do
    all_newspapers = Newspaper.all
    filtered_newspapers = all_newspapers.select { |newspaper| newspaper.done == false }
    @todays_paper = filtered_newspapers.first
    @todays_paper.done = true
    @todays_paper.save
    return @todays_paper
  end
end

My question is, how do I pass the @todays_paper instance variable to the controller, and therefore to the view? If I call this in the controller action, even if I'm using Whenever or Sidekiq to run it every 24 hours, it will still run every time the controller action is called, I think.

I don't know whether this is the wrong approach - but I can't think of another way of scheduling this to happen than using a background job. Could I use a Newspaper class method, that could be called perhaps?

1

There are 1 answers

3
Tom Lord On

Option 1: Run a cron job once per day. A popular library for this is clockwork.

You could trigger a cron job via clockwork ... Or not ... That's an implementation detail which is up to you! But basically, you need it to do something like this:

every(1.day, 'Update live newspaper', at: '00:00') do
  current_newspaper = Newspaper.find_by(live: true)
  next_newspaper = Newspaper.find_by(done: false)

  current_newspaper.update_attributes({live: false})
  next_newspaper.update_attributes({live: true, done: true})
end

And then in the controller, just fetch:

@live_newspaper = Newspaper.find_by(live: true)

Note that I've assumed a second attribute (live) on the newspapers table; otherwise there's no way to identify it.

As I said, you could move the above code into a job, or a rake task, or whatever - and invoke it from the scheduler - instead of writing all the code inline. That's up to you.


Option 2: Alternatively, you could do something clever by automatically rotating the newspaper a soon as someone views the website each day.

For example, what if instead of using done as a boolean field, you make it a live_on date field? Then you could do something like this in the controller:

@current_newspaper = Newspaper.find_by(live_on: Date.today) || set_todays_newspaper

...

def set_todays_newspaper
  newspaper = Newspaper.find_by(live_on: nil)
  newspaper.update_attributes({live_on: Date.today})
  newspaper
end