Richlewis
Richlewis

Reputation: 15394

Handling a reoccurring event in Rails 4

I was looking at ways to implement logic for reoccurring events. I would like to display events for the upcoming week, dependent upon their recurrence.

For example I have 2 events, one is weekly and the other is two weekly, In my view for this week I would only show the one event, but come next week there would be two showing.

So far I have my models set up like so in the migration file ready to be created

class CreateEvent
  create_table :events do |t|
   t.string :title
   t.text :description
   t.time :time_from
   t.time :time_to
   t.date :next_date
   t.string :day
   t.timestamps null: false
 end 
end
# An Event `has_one` Frequency

class CreateFrequency
  create_table :frequencies do |f|
    f.string :occurs
    f.integer :event_id
    t.timestamps null: false
  end
end
# Was Thinking of pre populating this with Weekly and 2 weekly
# A frequency `belongs_to` Event

I am trying to keep this as simple as possible, so would I need to implement some kind of logic where I would do a calculation starting with the Events next_date and counting the weeks passed up to today's. Not quite sure here.

Could I even go down the route of having a flag in the event model, a column called display (boolean) and have a Rake task that will update it again using the next_date? Would that work? I am unsure of the logic there, mind.

Upvotes: 1

Views: 152

Answers (2)

Rob Falken
Rob Falken

Reputation: 2297

You could store the frequency in the event table, (1 for every week, 2 for every two weeks) and then use some math to figure out if the upcoming week is an even amount of weeks after the original date, something like this:

Event.where("(extract(week from NOW())::int - extract(week from time_from)::int) % 2 = 1 OR frequency = 1")

This should grab all events that are either in its "2 week cycle" next week, or has its frequency set to 1.

Note: This will work for postgres at least, but you would need to change the data type to datetime instead of just time.

If you already have next_date stored for the events, then you can use a time range to select all events in the upcoming week:

start_date = Date.today.beginning_of_week + 7.days
end_date = start_date + 6.
@events = Event.where(next_date: start_date..end_date)

Note: I read "upcoming week" as "next week", you'd have to modify it at bit if you wish for a different behaviour.

Upvotes: 2

makhan
makhan

Reputation: 4019

I'd recommend you store the original date of the event in the database, and calculate the next event inside your model.

def frequency
  case occurs
  when 'weekly'
    1.week
  when 'biweekly'
    2.week
  end
end

def next_event  
  event_no = ((Time.now-first_event)/frequency).floor+1
  return first_event +  event_no*frequency
end

def event_next_week?
  next_event < Time.now+1.week
end

To avoid having to do calculations every time user requests a list of events you can have a CRON job or some other sort of recurring job that would calculate the dates of next events at the beginning of each week and save them to database.

Rather than as a string, you could store the frequency as number of days or weeks.

Keeping a variable 'display' would be troublesome if you want to display events for the next 7 days and you want to stop displaying an event once it ends. Date is more flexible:

@events = Event.where('next_event > ? AND next_event < ?', Time.now, Time.now+7.days)

Upvotes: 2

Related Questions