Here’s the scoop;
I had a need to send emails to users at a specific interval in a time period based on two simple conditions:

  1. Is it the right day?
  2. Does this user want emails? (Did they opt out yet?)

I elected to run a cron every day at a specific time (using the whenever gem). When it runs, the date is compared to is_nag_time. If true, every user is looped through checking the latter condition. Let’s get to some code

I've tried to include the crucial stuff here from a previous app I built, but it may not work out of the box.
def get_date_diff
  # Get the difference in weeks or months
  if self.weekly?
    return ( - self.start_date.cweek).weeks
  elsif self.monthly?
    return ( - self.start_date.year) * 12 + - self.start_date.month - ( >= ? 0 : 1).months

def current_survey_date
  return self.start_date + (self.get_date_diff - 1).days

def is_nag_time
  return self.current_survey_date + ( * 0.75).round.days

def current_survey
  return self.surveys.find_by_position(self.get_date_diff.to_i)

# Determine the current iteration date (current_step_date)
# Add Time percentage to it based on the iteration (weekly or monthly)
def self.do_the_nag
  if program.is_nag_time ==
    time_to_nag =
    counter = 1

    # Loop through users
      .where(:email_opt_in => true)
      .each do |user|

      if counter > 50
        counter = 1
        time_to_nag = time_to_nag + 1.minute

      NagMailer.delay(:run_at => time_to_nag).next_survey_reminder(user, program)


# schedule.rb
every, :at => '10am' do
  runner 'Program.do_the_nag'

I think the code is fairly straight forward. I choose to run it on a daily basis, instead of just scheduling the emails in the future, because the dates may change at any given time. I believe this accomidates for most, if not all, situations.