[Ruby/Rails] Calculate expected publication dates for posting queue
New here? Learn about Bountify and follow @bountify to get notified of new bounties! x

I have a custom built blog that has a publication queue. At specific times throughout the day the system publishes the next post in line. I'd like to add an 'expected publication date' to each of the posts inside the queue.

For the purpose of this bounty let's say the following:

I have specified the hours of the day posts will be published using an array as follows:
queue_hours = [12, 14, 16] (I may add/change hours at a later stage)

I use the following code in hourly cron job to see if should publish the next post:
Post.order('schedule_position ASC, scheduled_at ASC').scheduled.first if queue_hours.include?(Time.now.getgm.hour)

Lets assume the cron job runs 15 minutes past every hour ( 00:15, 01:15, 02:15 ).

Posts in the queue are ordered by schedule_position (integer) and then scheduled_at (datetime).

I have a page that shows the scheduled posts ordered by the method described above. Next to each post I'll want to show the expected publication date. I'd like it to be an instance method of the Post-model (ActiveRecord).

awarded to ctcherry

Crowdsource coding tasks.

1 Solution

Winning solution

This should get you all of the way or most of the way there. I'm assuming I can access the queue_hours array directly, which might not be the case.

class Post

  def expected_publication_date

    # First we get all of the posts that are set to go out before the
    # instance of the post we are currently in
    posts_before_self = self.class.where("(scheduled_at < :self_sch_at) OR ( scheduled_at = :self_sch_at AND schedule_position < :self_sch_pos)", {:self_sch_at => self.scheduled_at, :self_sch_pos => schedule_position}).order('schedule_position ASC, scheduled_at ASC').scheduled

    # See how many posts we send out per day
    sends_per_day = queue_hours.length

    # Divide those numbers and round down, so factional days become zero
    days_til_send = (posts_before_self.count/sends_per_day).floor

    # Find estimated queue_hour of send

    current_gmh = Time.now.getgm.hour

    remaining_queue_hours_today = queue_hours.select { |h| h > current_gmh }

    queue_hour_start_offset = sends_per_day - remaining_queue_hours_today.length

    send_distance = posts_before_self.count + queue_hour_start_offset

    i = send_distance % queue_hours.length

    # Found estimated queue_hour
    send_hour = queue_hours[i]

    # Return the current date, with the above calculated numbers of days
    # added to it and then add the queue_hour we found
    Time.now.to_date + days_til_send.days + send_hour.hours

  end

end
Thanks, this is almost exactly what I want, but it doesn't include the specific time the post will be published. To calculate this I think it should not round down the daystilsend number and at the last code line it should check what's the first publication time after the datetime the method now returns.
marc 9 years ago
Ah ok, I saw that date was specified in the answer, I've updated my answer to find the estimated hour of send as combine it with the date. I can't test it obviously so I hope this works or sets you in the right direction.
ctcherry 9 years ago
I think it's very close, but still has two bugs I can see: 1) Try running the numbers where the current time is after the last queue hour and there are no post scheduled before this one. In reality the post will be published tomorrow at the first queue hour. However, the code estimates it will be published TODAY at the first queue hour which has already past. 2) The code doesn't consider the fact the posts are published at 15 minutes past the queue hour as mentioned in the opening question. I haven't ran the numbers yet but I expect the code will estimate wrong when running it anywhere between xx:00 and xx:15. As I wasn't totally clear in my opening question to include the time as well I'll bump the bounty to $15. (Site doesn't allow me to change bounty, but I'll simply tip you $5 extra when everything is completed.)
marc 9 years ago
I've awarded the bounty. Thanks! I will tip extra if you can solve the problem mentioned above.
marc 9 years ago