2

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 ;)

Daithí
  • 4,717
  • 5
  • 26
  • 35

1 Answers1

2

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.

Netzpirat
  • 5,481
  • 1
  • 22
  • 21
  • @Netpirat your answer has brought me 50% there, cheers `rake watcher` now coppies everything from `src` to `dist` but then fails to watch the files. If i run `guard` from the cmd line the files are watched successfully. Could there be another call in the watcher:task needed, such as guard-listen? – Daithí Apr 12 '13 at 09:41
  • @Coombesy If you also want the file watchers, you need to start Listen with `Guard.start` – Netzpirat Apr 12 '13 at 14:20
  • thanks for the tip. If I replace `Guard.setup` with `Guard.start` then it will copy the files but still won't watch the folder. If I call both `setup` and `start` I get `Hook with name 'load_guard_rc' already defined!` - The guard file is also still working when I call `guard` from the shell – Daithí Apr 12 '13 at 15:42
  • @Coombesy You can avoid the error by disabling the interactor, which you anyway don't need in the task: `Guard.setup({ no_interactions: true })` – Netzpirat Apr 12 '13 at 16:18
  • Still no joy, i've updated the code in your answer to reflect the current rake file. `bundle exec guard` and `guard` are still working as expected, but `rake watcher` copies everything but still doesn't watch the folders :( – Daithí Apr 12 '13 at 16:45