Daithí
Daithí

Reputation: 4079

ruby rake guard task

Ruby noob - I need to have guard running in my rake tasks but I can't find a way to have it run in the background. It needs to run 2nd last, therefore having the guard > shell waiting for commands is preventing the final task from running, so calling sh bundle exec guard in the rake file is not an option. According to the documentation this should work:

  ##
  desc "Watch files"
  ##
  task :watcher do
    Guard.setup
    Guard::Dsl.evaluate_guardfile(:guardfile => 'Guardfile', :group => ['Frontend'])
    Guard.guards('copy').run_all
  end
  #end watch files

https://github.com/guard/guard/wiki/Use-Guard-programmatically-cookbook

Here is my Guardfile, in full, (in same dir as Rakefile)

# Any files created or modified in the 'source' directory
# will be copied to the 'target' directory. Update the
# guard as appropriate for your needs.
guard :copy, :from => 'src', :to => 'dist', 
            :mkpath => true, :verbose => true

But rake watcher returns an error:

07:02:31 - INFO - Using Guardfile at Guardfile.
07:02:31 - ERROR - Guard::Copy - cannot copy, no valid :to directories
rake aborted!
uncaught throw :task_has_failed

I have tried different hacks, too many to mention here, but all have returned the above Guard::copy - cannot copy, no valid :to directories. The dist directory definitely exists. Also if I call guard from the shell, inside rake or on cmd line, then it runs perfect, but leaves me with the guard > shell. Think my issue maybe a syntax error in the rake file? any help appreciated ;)

Upvotes: 2

Views: 1421

Answers (1)

Netzpirat
Netzpirat

Reputation: 5501

Guard Copy does some initialization in the #start method, so you need to start the Guard before you can run it:

task :watcher do
  Guard.setup
  copy = Guard.guards('copy')
  copy.start
  copy.run_all
end

In addition there's no need to call Guard::Dsl.evaluate_guardfile anymore, that info on the wiki is outdated.

Edit 1: Keep watching

When you want to watch the dir, then you need to start Guard:

task :watcher do
  Guard.start
  copy = Guard.guards('copy')
  copy.start
  copy.run_all
end

Note: If you setup Guard and start it afterwards, then Guard fails with Hook with name 'load_guard_rc'

Edit 2: Really keep watching

Guard starts Listen in non blocking mode, so in order to make the call blocking, you need to wait for it:

task :watcher do
  Guard.start
  copy = Guard.guards('copy')
  copy.start
  copy.run_all
  while ::Guard.running do
    sleep 0.5
  end
end

If you also want to disable interactions, you can pass the no_interactions option:

Guard.start({ no_interactions: true })

The API is absolutely not optimal and I'll improve it for Guard 2 when we remove Ruby 1.8.7 support and some deprecated stuff.

Upvotes: 2

Related Questions