How to create custom rake tasks with multiple arguments? - ruby-on-rails

I want to create a custom rake task with supporting multiple arguments.
When finished I want to call the rake task like:
rails conifg:load -i 5 -o "now" ...
How to create them ?
The (rubyonrails guides) says :
task :task_name, [:arg_1] => [:prerequisite_1, :prerequisite_2] do |task, args|
argument_1 = args.arg_1
end
But I dont understand it.

When finished I want to call the rake task like:
rails conifg:load -i 5 -o "now" ...
You can't, that is not how you pass arguments to Rake tasks, those arguments (-i, -o, etc) are passed to Rake itself, not to your task.
Instead, there are a few options:
Use thor which has (in my opinion) a far superior API, and allows for traditional Unix style arguments (-i, --help, etc). You can easily produce a script that would be invoked with:
thor config:load -i 5 -o "now"
Use Rake's argument system, where you would pass arguments in the form
rails config:load[5,now]
Build your own script, placed in bin. For example, bin/config can accept arbitrary arguments, and be invoked however you like. Any of the following are possible:
./bin/config load -i 5 -o now
./bin/load_config i=5 o=now
./bin/config.load 5 now
# etc

Related

Optionally allowing STDIN to be passed to a rake task

I have a rake task that I would like to be optionally given stdin, e.g. either of the following could work:
rake my_task
cat foo.txt | rake my_task
The problem is that I don't have a reliable way to check whether STDIN was given to the program. Here's my current attempt, which just hangs indeterminately:
instructions = STDIN.read.split("\n") if STDIN.tty?
I added the STDIN.tty? after reading how-can-you-check-for-stdin-input-in-a-ruby-script. It is returning true when I invoke it with rake my_task (no stdin)
You just need to invert the condition. What you want is to read stdin if it’s not a tty:
instructions = STDIN.read.split("\n") unless STDIN.tty?

Rspecs Failed with Test::Unit automatic runner messages

versions
ruby 2.0.0p451 (2014-02-24 revision 45167) [x86_64-linux]
rails-3.2.18
rspec-2.14.1
parallel_tests-0.9.3
configs
.rspec
--color
--format documentation
--drb
--profile
.rspec_parallel
If installed as plugin: -I vendor/plugins/parallel_tests/lib
--color
--format documentation
--profile
when normal rspec success and not output Test unit messages
% RAILS_ENV=test bundle exec rspec
when parallel_tests rspec failed and output Test Unit messages
% RAILS_ENV=test bundle exec rake parallel:create\[4\] db:migrate parallel:prepare\[4\]
% RAILS_ENV=test bundle exec rake parallel:spec\[4\]
error
invalid option: -O
Test::Unit automatic runner.
Usage: /var/lib/jenkins/jobs/anyone.develop.spec/workspace/vendor/bundle/ruby/2.0.0/bin/rspec [options] [-- untouched arguments]
-r, --runner=RUNNER Use the given RUNNER.
(c[onsole], e[macs], x[ml])
--collector=COLLECTOR Use the given COLLECTOR.
(de[scendant], di[r], l[oad], o[bject]_space)
-n, --name=NAME Runs tests matching NAME.
(patterns may be used).
--ignore-name=NAME Ignores tests matching NAME.
(patterns may be used).
-t, --testcase=TESTCASE Runs tests in TestCases matching TESTCASE.
(patterns may be used).
--ignore-testcase=TESTCASE Ignores tests in TestCases matching TESTCASE.
(patterns may be used).
--location=LOCATION Runs tests that defined in LOCATION.
LOCATION is one of PATH:LINE, PATH or LINE
--attribute=EXPRESSION Runs tests that matches EXPRESSION.
EXPRESSION is evaluated as Ruby's expression.
Test attribute name can be used with no receiver in EXPRESSION.
EXPRESSION examples:
!slow
tag == 'important' and !slow
--[no-]priority-mode Runs some tests based on their priority.
--default-priority=PRIORITY Uses PRIORITY as default priority
(h[igh], i[mportant], l[ow], m[ust], ne[ver], no[rmal])
-I, --load-path=DIR[:DIR...] Appends directory list to $LOAD_PATH.
--color-scheme=SCHEME Use SCHEME as color scheme.
(d[efault])
--config=FILE Use YAML fomat FILE content as configuration file.
--order=ORDER Run tests in a test case in ORDER order.
(a[lphabetic], d[efined], r[andom])
--max-diff-target-string-size=SIZE
Shows diff if both expected result string size and actual result string size are less than or equal SIZE in bytes.
(1000)
-v, --verbose=[LEVEL] Set the output level (default is verbose).
(important-only, n[ormal], p[rogress], s[ilent], v[erbose])
--[no-]use-color=[auto] Uses color output
(default is auto)
--progress-row-max=MAX Uses MAX as max terminal width for progress mark
(default is auto)
--no-show-detail-immediately Shows not passed test details immediately.
(default is yes)
--output-file-descriptor=FD Outputs to file descriptor FD
-- Stop processing options so that the
remaining options will be passed to the
test.
-h, --help Display this help.
Deprecated options:
--console Console runner (use --runner).
Coverage report Rcov style generated for RSpec to /var/lib/jenkins/jobs/anyone.develop.spec/workspace/coverage/rcov
Rspecs Failed
try to
https://github.com/grosser/parallel_tests/issues/189
add spec_helper.rb
Test::Unit::AutoRunner.need_auto_run = false if defined?(Test::Unit::AutoRunner)
But, It did not resolve
delete spork
add
Test::Unit::AutoRunner.need_auto_run = false if defined?(Test::Unit::AutoRunner)
spec_helper.rb last line
resolved!
try this on your Gemfile
gem "test-unit", :require => false
or try test-unit 3.1.5.
https://github.com/test-unit/test-unit/issues/32#issuecomment-146885235
someone says about broke the application to run on Heroku. but likely the same as your problem

How long should "rake routes" run?

I just started out with Rails, so excuse my fairly basic question. I am already noticing that the rake routes command takes a while to execute everytime I run it. I have about 20 routes for 3 controllers and it takes about 40 seconds to execute.
Is that normal? How could I speed this up?
P.S.: I am on Windows 7 with Rails 3.1.3 (set up with Rails Installer).
The rake routes task depends on the environment task which loads your Rails environment and requires thousands of Ruby files.
The startup time of a Rails environment and the corresponding rake routes execution time are very close (on my Linux on-steroids-laptop with a Rails application with ~ 50 routes):
$ time ruby -r./config/environment.rb -e ''
real 0m5.065s
user 0m4.552s
sys 0m0.456s
$ time rake routes
real 0m4.955s
user 0m4.580s
sys 0m0.344s
There is no easy way to decrease startup time as it relies on the way your interpreter requires script files : http://rhnh.net/2011/05/28/speeding-up-rails-startup-time
I came up with a solution to rake routes taking about 8 seconds to run every time. It's a simple file based cache that runs bundle exec rake routes, stores the output in a file under tmp. The filename is the md5 hash of config/routes.rb, so if you make a change and change it back, it will use the old cached file.
I put the following bash functions in an executable file I call fastroutes:
if [ ! -f config/routes.rb ]; then
echo "Not in root of rails app"
exit 1
fi
cached_routes_filename="tmp/cached_routes_$(md5 -q config/routes.rb).txt"
function cache_routes {
bundle exec rake routes > $cached_routes_filename
}
function clear_cache {
for old_file in $(ls tmp/cache_routes*.txt); do
rm $old_file
done
}
function show_cache {
cat $cached_routes_filename
}
function show_current_filename {
echo $cached_routes_filename
}
function main {
if [ ! -f $cached_routes_filename ]; then
cache_routes
fi
show_cache
}
if [[ "$1" == "-f" ]]
then
show_current_filename
elif [[ "$1" == "-r" ]]
then
rm $cached_routes_filename
cache_routes
else
main
fi
Here's a github link too.
This way, you only have to generate the routes once, and then fastroutes will used the cached values.
That seems a bit long, but do you really need to run rake routes that often? On my system, OSX Lion/Rails 3.2.0, rake routes takes ~10s.
In your Rakefile:
#Ouptut stored output of rake routes
task :fast_routes => 'tmp/routes_output' do |t|
sh 'cat', t.source
end
#Update tmp/routes_output if its older than 'config/routes.rb'
file 'tmp/routes_output' => 'config/routes.rb' do |t|
outputf = File.open(t.name, 'w')
begin
$stdout = outputf
Rake.application['routes'].invoke
ensure
outputf.close
$stdout = STDOUT
end
end
Rails environment takes a huge more amount of time to be loaded on Windows. I recommend you to give Unix a try, like Ubuntu, as Windows is the worst environment in which you can run and develop Ruby on Rails applications. But if you are just trying Rails, Windows is enough :)

How I can call specified first app's rake task from second one

How can I call specified 1st app's rake task from second one.
Case:
User on baseapp.com (RoR), fills up the reg.form
BaseApp validates and stores data
Than, with delayed_job/resque I should call subapp's rake db:bootstrap FORM_PARAM1 FORM_PARAM2 ... FORM_PARAM3
You need define the Rakefile you want load to your rake execution
rake -f my_dir_1/Rakefile my_task
rake -f my_dir_2/Rakefile my_task_2

unix at command pass variable to shell script?

I'm trying to setup a simple timer that gets started from a Rails Application. This timer should wait out its duration and then start a shell script that will start up ./script/runner and complete the initial request. I need script/runner because I need access to ActiveRecord.
Here's my test lines in Rails
output = `at #{(Time.now + 60).strftime("%H:%M")} < #{Rails.root}/lib/parking_timer.sh STRING_VARIABLE`
return render :text => output
Then my parking_timer.sh looks like this
#!/bin/sh
~/PATH_TO_APP/script/runner -e development ~/PATH_TO_APP/lib/ParkingTimer.rb $1
echo "All Done"
Finally, ParkingTimer.rb reads the passed variable with
ARGV.each do|a|
puts "Argument: #{a}"
end
The problem is that the Unix command "at" doesn't seem to like variables and only wants to deal with filenames. I either get one of two errors depending on how I position "s
If I put quotes around the right hand side like so
... "~/PATH_TO_APP/lib/parking_timer.sh STRING_VARIABLE"
I get,
-bash: ~/PATH_TO_APP/lib/parking_timer.sh STRING_VARIABLE: No such file or directory
I I leave the quotes out, I get,
at: garbled time
This is all happening on a Mac OS 10.6 box running Rails 2.3 & Ruby 1.8.6
I've already messed around w/ BackgrounDrb, and decided its a total PITA. I need to be able to cancel the job at any time before it is due.
After playing around with irb a bit, here's what I found.
The backtick operator invokes the shell after ruby has done any interpretation necessary. For my test case, the strace output looked something like this:
execve("/bin/sh", ["sh", "-c", "echo at 12:57 < /etc/fstab"], [/* 67 vars */]) = 0
Since we know what it's doing, let's take a look at how your command will be executed:
/bin/sh -c "at 12:57 < RAILS_ROOT/lib/parking_timer.sh STRING_VARIABLE"
That looks very odd. Do you really want to pipe parking_timer.sh, the script, as input into the at command?
What you probably ultimately want is something like this:
/bin/sh -c "RAILS_ROOT/lib/parking_timer.sh STRING_VARIABLE | at 12:57"
Thus, the output of the parking_timer.sh command will become the input to the at command.
So, try the following:
output = `#{Rails.root}/lib/parking_timer.sh STRING_VARIABLE | at #{(Time.now + 60).strftime("%H:%M")}`
return render :text => output
You can always use strace or truss to see what's happening. For example:
strace -o strace.out -f -ff -p $IRB_PID
Then grep '^exec' strace.out* to see where the command is being executed.

Resources