ruby rake guard task - ruby

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

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.

Related

Where do I find my whenever log files?

I'm using the whenever gem for Rails 5. I'm trying to troubleshoot an issue, and after my default schedule.rb file was created at config/schedule.rb, I added some logging directives
# Learn more: http://github.com/javan/whenever
set :environment, "development"
every 10.minutes do
rake "events:calc_index", :output => {:error => 'error.log', :standard => 'cron.log'}
end
I restarted my Rails server (not sure if that matters or not) but I don't see these log files created anywhere. I have verified my crontab was set up by running "crontab -e" and seeing the job
0,10,20,30,40,50 * * * * /bin/bash -l -c 'cd /Users/davea/Documents/workspace/newproj && RAILS_ENV=development bundle exec rake events:calc_index '
Where are the log files created?
In your schedule.rb file you can specify the redirection options for your commands at a global or command level by setting the 'output' variable. This example is global level:
# adds ">> /path/to/file.log 2>&1" to all commands
set :output, '/path/to/file.log'
and you should put this global level set :output above your job definition, otherwise it wouldn't work
Example:
# This works
set :output, {:error => '~/Desktop/z.error.log', :standard => '~/Desktop/z.standard.log'}
every 1.minute do
command "python ~/Desktop/whe/config/z.py"
end
Taken from: https://github.com/javan/whenever/wiki/Output-redirection-aka-logging-your-cron-jobs
According to whenever documentation
https://github.com/javan/whenever/wiki/Output-redirection-aka-logging-your-cron-jobs
you can define output like this with Rails :
set :output, "#{path}/log/cron.log"
So for your exemple you can do :
every 10.minutes do
rake "events:calc_index", output: {error: "#{path}/log/error.log", standard: "#{path}/log/cron.log"}
end

Cannot rerun my app with guard or rerun

So I have an app, the tree is something like this:
- Gemfile
- Guardfile
- source/
- dist/
- app.rb
The command to start the server is ruby app.rb ( or require_relative './app.rb', which does the same thing)
I want to run this command and re run it whenever any file changes.
The only exception is the dist/ folder - any file changes in there should be ignored.
Here's my attempt so far with guard and guard-shell (apologies for the code dump):
require 'childprocess'
# Global constant tracking whether the app has been started
RunningProcess = {gen_rb: false}
# Method to stop the app if it's been started
def ensure_exited_server
begin
RunningProcess[:gen_rb] && RunningProcess[:gen_rb].poll_for_exit(10)
rescue ChildProcess::TimeoutError
RunningProcess[:gen_rb].stop # tries increasingly harsher methods to kill the process.
end
nil
end
# Start the app using 'child-process'
def start_app
# prevent 'port in use' errors
ensure_exited_server
# The child-process gem starts a process and exposes its stdout
RunningProcess[:gen_rb] = ChildProcess.build("ruby", "gen.rb")
RunningProcess[:gen_rb].io.inherit!
RunningProcess[:gen_rb].start
nil
end
# Always start the app, not just when a file changes.
start_app
# The guard-shell gem runs a block whenever some set of files has changed.
guard :shell do
# This regex matches anything except the dist/ folder
watch /^[^dist\/].+/ do |m|
start_app
# Print a little message when a file changes.
m[0] + " has changed."
end
nil
end
# Make sure the app does not run after guard exits
at_exit { ensure_exited_server }
This doesn't ever restart my app.
The problem with rerun is something I raised an issue on their repo about: see https://github.com/alexch/rerun/issues/107
How about something like this for your Guardfile?
guard :shell do
watch(%r{^source/.+\.(rb)}) do |m|
`ruby app.rb`
end
watch('app.rb') do |m|
`ruby app.rb`
end
end
Instead of listing which directories to ignore, this watch states which directories/files to use.

Ruby Guard Watch is behaving really slow

Im using latest version of Guard and Guard-Haml. I have 7 maps in my root dir where i store Haml files in two different directories. One is in /templates/haml and one is in /haml. The total sum of the haml files is less than 10.
In the other 5 maps I have about 17 000 files. I have configured guard to only watch in the /haml and /templates/haml maps for change. It works fine just after I started with bundle exec guard, but after a while it gets slow as hell. About 30 seconds from where I make a change to a file does it take it to recompile the file.
This is my Guardfile
require 'haml/helpers'
require 'haml/filters'
require 'haml/filters/php'
guard :haml, input: 'www/templates/haml', output: 'www/templates', :haml_options => { :escape_attrs => false } do
watch %r{^www/templates/haml/.+(\.haml)$}
end
guard :haml, input: 'www/haml', output: 'www/', :haml_options => { :escape_attrs => false } do
watch %r{^www/haml/.+(\.haml)$}
end
Is there anything I can do to speed this up because its really slowing my dev. down.
I found out that I could use the ignore command and ignore out all directories I didn't want guard to look at.
Example:
ignore([%r{^node_modules/*}])
Link to more details about this
You can only watch those two folders when you start guard:
bundle exec guard --watchdir www/templates/haml www/haml

Ruby Guard ignore files

I would like to run the requirejs optimization script when any .js file is changed (except for built.js).
I read there is an ignore method. I have the following in my Gaurdfile (which is causing an infinite loop).
guard 'shell', :ignore => 'built.js' do
watch(/script\/(.*).js/) { `node r.js -o build.js` }
end
My question is: How do I configure my Guardfile to ignore the file built.js?
First, assuming you already have the guard-shell gem installed...
I think this gives you something to work from given what you are trying to do.
It will ignore the script/build.js file and trigger a shell command when any other .js file changes.
ignore /script\/build.js/
guard :shell do
watch /.*\.js/ do |m|
`yourcommandhere`
msg = "Processed #{m[0]}"
n msg, 'mycustomshellcommand'
"-> #{msg}"
end
end
See this link for Guardfile examples.
See this link for the syntax of guard-shell.

Why does my system call work in the irb but not in a rake task?

I try to run system "./do_backup.py" within my rake task, where do_backup.py is a python program in the same directory, but the command fails silently. I can run it using system "./do_backup.py", however.
I called system "whoami" from both within my rake task and the IRB, and the users are the same.
EDIT
Here's the rakefile:
desc "Back up a file onto S3"
task :backup do
S3ID = "AKIAJM3NRWxxx"
S3KEY = "0A5kuzV+E1dkaPjxxx"
SRCBUCKET = "rose-test-4"
NUM_BACKUP_BUCKETS = 2
system "whoami"
system "./do_backup.py #{S3ID} #{S3KEY} #{SRCBUCKET} #{NUM_BACKUP_BUCKETS}"
end
As discussed in the comments, this was being run from the wrong directory. You can change directories with Dir.chdir(). For example:
...
Dir.chdir("lib/tasks")
system "./do_backup.py #{S3ID} #{S3KEY} #{SRCBUCKET} #{NUM_BACKUP_BUCKETS}"
end
Of course, as #muistooshort points out, the simpler thing is to just run it from where it is:
system "#{Rails.root}/lib/tasks/do_backup.py #{S3ID} #{S3KEY} #{SRCBUCKET} #{NUM_BACKUP_BUCKETS}"

Resources