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 (Date.today.cweek - self.start_date.cweek).weeks
  elsif self.monthly?
    return (Date.today.year - self.start_date.year) * 12 + Date.today.month - self.start_date.month - (Date.today.day >= self.start_date.day ? 0 : 1).months
  end
end

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

def is_nag_time
  return self.current_survey_date + (Date.today.end_of_month.day * 0.75).round.days
end

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

# 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 == Date.today
    time_to_nag = Time.now
    counter = 1

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

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

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

    end
  end
end

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

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.