I inherited a project with a lot of badly-written Rake tasks that I
need to clean up a bit. Because the Rakefiles are enormous and often
prone to bizarre nonsensical dependencies, I’m simplifying and
isolating things a bit by refactoring everything to classes.
Specifically, that pattern is the following:
namespace :foobar do desc "Frozz the foobar." task :frozzify do unless Rake.application.lookup('_frozzify') require 'tasks/foobar' Foobar.new.frozzify end Rake.application['_frozzify'].invoke end # Above pattern repeats many times. end # Several namespaces, each with tasks that follow this pattern.
tasks/foobar.rb, I have something that looks like this:
class Foobar def frozzify() # The real work happens here. end # ... Other tasks also in the :foobar namespace. end
For me, this is great, because it allows me to separate the task
dependencies from each other and to move them to another location
entirely, and I’ve been able to drastically simplify things and
isolate the dependencies. The Rakefile doesn’t hit a
you actually try to run a task. Previously this was causing serious
issues because you couldn’t even list the tasks without it blowing up.
My problem is that I’m repeating this idiom very frequently. Notice
the following patterns:
For every namespace
:xyz_abc, there is a corresponding class in
tasks/...in the file
tasks/[namespace].rb, with a class name that
For every task in a particular namespace, there is an identically
named method in the associated namespace class. For example, if
:foo_barhas a task
:apples, you would expect to see
def apples() ...inside the
FooBarclass, which itself is in
:tdefines a “meta-task”
_t(that is, the task name
prefixed with an underscore) which is used to do the actual work.
I still want to be able to specify a
desc-description for the tasks
I define, and that will be different for each task. And, of course, I
have a small number of tasks that don’t follow the above pattern at
all, so I’ll be specifying those manually in my Rakefile.
I’m relatively sure that this can be refactored with metaprogramming
in some way so that I don’t have to keep repeating the same idiom over
and over, but I lack the experience to see how it could be done, or
whether I’m even on the right track at all. Any thoughts or advice to
point me in the right direction?