Task contains enqueue_at an optional attribute that defines when (hour and minute) the job should be enqueued. If the attribute is not present, the current time should be used.
# tasks (id INT, enqueue_at DATETIME, action VARCHAR(255))
class Task < ActiveRecord::Base
end
Each day we need to enqueue all of the tasks. Below are two examples and I'm looking for opinions on which is better and why.
Task.all.each do |task|
if task.enqueue_at
enqueue_at = Time.now.change(:hour => task.enqueue_at.hour, :min => task.enqueue_at.min)
Q.enqueue_at(enqueue_at, Task, task.id)
else
Q.enqueue(Task, task.id)
end
end
class Task
def enqueue(queue = Q)
if enqueue_at
enqueue_at = Time.now.change(:hour => enqueue_at.hour, :min => enqueue_at.min)
queue.enqueue_at(enqueue_at, Task, id)
else
queue.enqueue(Task, id)
end
end
end
Task.all.each do |task|
task.enqueue
end
I was actually working on code very similar to this today, which is what inspired me to ask for feedback. Today I chose to write Example 2, but on another day I may have written Example 1.
Example 1 may be able to be tested without loading ActiveRecord, but enqueuing a task requires reaching into each Task object to see if enqueue_at is set and to get the id.
Example 2 requires ActiveRecord to be loaded in order to write tests against it. However, it only requires knowledge of Q and it's interface, enqueue and enqueue_at.
Example 1 would be preferable if you expected to have different enqueing strategies, I think, because it would be external to the Task class and could be more easily swapped out with a different strategy.
But, if you don't expect to need different enqueing strategies I think Example 2 is the clear winner. Example 2 is better encapsulated (you don't have to expose the "enqueue_at" field outside of the class). It also takes the Q as a parameter which should make it more testable since you could supply a stubbed implementation of Q during test time as opposed to depending on a concrete instance as in Example 1. I also like the separation of the selection of Tasks and the enqueueing of tasks (which could be done in Example 1 by extracting a helper function as well I guess)
FWIW