Search code examples
ruby-on-railsrubyrake

How do I stop rake from treating a file dependency as a possible task name?


Short version:

I have a problem: a file dependency I need for one rake task matches the name of another rake task, so instead of depending on the file, rake tries to depend on the task with the matching name.

How do I tell rake to only match a dependency to a file? Is there some other way out?

Long version:

I'm trying to create a rake task in my Rails application that zips up all the files I care about. That's it. Easy.

I'd also appreciate the normal dependency testing in rake: if no files have changed and the zip file already exists, don't do anything.

The issue is that one of the files that I want to include in the zip file (and thus treat as a task dependency) is the test directory, but rake test happens to be an existing rake task. If I say something like:

# FILES_TO_INCLUDE being a Rake::FileList...
file 'output.zip' => FILES_TO_INCLUDE.to_a do
  ...
end

rake ends up running rake test as well.

Since I add files all the time, and since Rails changes the built-in rake tasks every now and then, I can never be sure that there won't be a conflict between rake tasks and file names.

What can I do to avoid this issue? Is there a better usage of rake that I'm missing?


Solution

  • I observe the same behavior. The FileTask, as defined by the file method in the rake DSL, inherits from the main Rake Task class and, indeed, invoking the dependencies (or in Rake's language prerequisities) seems to be the same for Tasks as well as FileTasks, i.e. if a file name is already defined as a rake task, the task is run instead.

    The only solution that comes to my mind is to add the path part to the files in FILES_TO_INCLUDE. It can be anything as simple as a "./" prefix.

    So, I'd try this instead:

    file 'output.zip' => FILES_TO_INCLUDE.map { |file| "./#{file}" } do
      ...
    end
    

    This approach seems to work OK for me.

    Also, for your particular scenario (creating a zip file of some other files), you can actually use a ready-made solution already present in Rake, the PackageTask:

    Rake::PackageTask.new("rake", "1.2.3") do |p|
      p.need_zip = true
      p.package_files.include("lib/**/*.rb")
    end
    

    This will create a rake-1.2.3.zip archive in the pkg (configurable) subdirectory. You probably will also need to prefix the files with some directory specification.