Issue One command and Run Multiple Ruby Files - ruby

I have to run a whole bunch of ruby scripts to generate some results. In which order does not matter. I just don't want to do Ruby file1.rb, Ruby file2.rb, Ruby file3.rb...one by one.
Could I write a script that group all files together and issue command only once to run them all?

I would do it ruby-style and use rake gem.
I would create file named "rakefile.rb" and this would be its content:
task :default do
FileList['file*.rb'].each { |file| ruby file }
end
Then I would call rake in my favourite shell and I would enjoy it.
Bonus: It's multiplatform.

Assuming you are using bash and all the ruby files you want to run are in the current directory you could do:
for file in `ls ./*.rb`; do
ruby $file
done

Have runall.rb contain:
(1..3).each do |i|
`ruby file#{i}.rb`
end
and call ruby runall.rb.

You could make a sh script called startruby.sh that looks like this (this example doesn't work):
ruby ruby1.rb;
ruby ruby2.rb;
etc.
And then run
sh startruby.sh
And it will lauch all the ruby script after each other.
Offcourse you can also make it more advanced with a for loop and such, but this is the easiest/quickest way.

Depends on what you want, but if you want all the files loaded together, maybe something like ...
ruby -I. -e "ARGV.each {|f| load f}" file*.rb

Related

how to build wrapper script

Sort of an odd question, but: how would one go about creating a wrapper shell script that can be used in the #! line in other scripts.
wrap.sh
#!/bin/bash
set -e
echo "wrapper!"
exec ruby "$#"
test.rb
#!/usr/bin/env wrap.sh
puts RUBY_VERSION
puts "the ducks come from the trucks"
wrap.sh is in the path, and test.rb is marked as executable.
Now I do:
./test.rb
wrapper!
ruby: no Ruby script found in input (LoadError)
The goal is to execute the ruby script via the wrapper (The ruby version can be either local or comes from a traveling ruby install that is shipped along with the app).
As far as I can tell ruby is invoked, it's just unhappy with the #! in the test.rb and refuses to run the script. I cannot remove the #! because that's how the script is executed in the first place.
Any workarounds for this?
So, I cannot use rbenv/rvm/etc. There is more logic in the wrapper than this, but this is the gist of it.
Looks to me like the arguments are not being passed to Ruby in "$#". I don't think the bang-hash line is the problem.
I don't see anything in your script which actually passes the contents of test.rb to wrapper.sh, which is the bigger issue.
Perhaps the real problem can be solved by some other means? For example, is the problem you're trying to solve to run arbitrary commands prior to the invocation of any Ruby script from the command line? Perhaps it can be approached that way...
It looks like Ruby just checks that the hash-bang line contains "ruby": https://github.com/ruby/ruby/blob/v2_2_2/ruby.c#L1580 So basically having ruby somewhere in the #! line is all it takes.

How can I use irb the Ruby interpreter to test/debug my .rb files?

How can I use irb the Ruby interpreter to test/debug my .rb files? I want to load an .rb file, let it run, and after it ends, get back to the irb prompt so I would be able to manipulate the variables which my script has built.
I tried load, require, and irb -r, but none of them worked as I would like. After the execution, when the program terminates, I get an irb prompt, but all of the variables are inaccessible. What can I do?
Not sure exactly what you want to do, but it sounds like you may want to use the "pry" gem instead.
Install the pry gem see: http://pryrepl.org
require 'pry' at the start of your program.
put binding.pry at the end of your program (or where you want to start the interactive session)
run your program.
Using pry you will have all your variables in scope.
More information see the link above, and here:
http://banisterfiend.wordpress.com/2011/01/27/turning-irb-on-its-head-with-pry/
and:
https://github.com/pry/pry/wiki/Runtime-invocation
If the variables you want are local variables, I do not think there is a way you can access them from another file.
If you just want the return value of the whole code that is on a different file, you can eval the whole content of that file within the main code and access the return value. You can access multiple values by putting them in an array or a hash at the end of the file to be evaled.
Add following code in place where you want irb to start
require 'irb'
IRB.start(__FILE__)
binding.irb
As of Ruby 2.4, placing this in your code will drop you into an irb session in the scope where it is placed.
No additional gem installs or require statements are needed.

Ruby run shell command in a specific directory

I know how to run a shell command in Ruby like:
%x[#{cmd}]
But, how do I specify a directory to run this command?
Is there a similar way of shelling out, similar to subprocess.Popen in Python:
subprocess.Popen(r'c:\mytool\tool.exe', cwd=r'd:\test\local')
Thanks!
You can use the block-version of Dir.chdir. Inside the block you are in the requested directory, after the Block you are still in the previous directory:
Dir.chdir('mydir'){
%x[#{cmd}]
}
Ruby 1.9.3 (blocking call):
require 'open3'
Open3.popen3("pwd", :chdir=>"/") {|i,o,e,t|
p o.read.chomp #=> "/"
}
Dir.pwd #=> "/home/abe"
also, taking the shell route
%x[cd #{dir} && #{cmd}]
The closest I see to backtricks with safe changing dir is capture2:
require 'open3'
output, status = Open3.capture2('pwd', :chdir=>"/tmp")
You can see other useful Open3 methods in ruby docs. One drawback is that jruby support for open3 is rather broken.
Maybe it's not the best solution, but try to use Dir.pwd to get the current directory and save it somewhere. After that use Dir.chdir( destination ), where destination is a directory where you want to run your command from. After running the command use Dir.chdir again, using previously saved directory to restore it.
I had this same problem and solved it by putting both commands in back ticks and separating with '&&':
`cd \desired\directory && command`

Pass ruby script file to rails console

Is there a way to pass ruby file, foo.rb to rails console. Expected results would be after console starts rails environment to run file.
Or any other way which would allow me to execute file in rails environment, triggered from command prompt.
Actually, the simplest way is to run it with load inside the rails console
load './path/to/foo.rb'
You can use
bundle exec rails runner "eval(File.read 'your_script.rb')"
UPDATE:
What we also have been using a lot lately is to load the rails environment from within the script itself. Consider doit.rb:
#!/usr/bin/env ruby
require "/path/to/rails_app/config/environment"
# ... do your stuff
This also works if the script or the current working directory are not within the rails app's directory.
In the meantime, this solution has been supported.
rails r PATH_TO_RUBY_FILE
Much simpler now.
Consider creating a rake task.
For code that I need to create records or support migrations, for example, I often create a rake task like that from this answer. For example:
In lib/tasks/example.rake:
namespace :example do
desc "Sample description you'd see if you ran: 'rake --tasks' in the terminal"
task create_user: :environment do
User.create! first_name: "Foo", last_name: "Bar"
end
end
And then in the terminal run:
rake example:create_user
script/console --irb=pry < test.rb > test.log
simple, dirty, and block the process at the end, but it does the job exactly like I wanted.
Of these approaches mentioned earlier, none seemed clean and ideal like you would expect a standalone script to run (not get eval-ed or piped via < redirection), but finally this works perfect for me:
(for Rails 3)
Insert at the top of your script:
#!/usr/bin/env ruby
APP_PATH = File.expand_path(appdir = '/srv/staging/strat/fundmgr/config/application', __FILE__)
require File.expand_path(appdir + '/../boot', __FILE__)
require APP_PATH
# set Rails.env here if desired
Rails.application.require_environment!
# your code here...
Of course, set your own Rails app path in the APP_PATH line.
That way, I can avoid having to enter any interactive irb or rails c and can test my script.rb from the shell prompt, before eg. scheduling it in crontab.
It smoothly supports command-line parameters, too, and minimizes the levels of wrappers before getting to your code.
CREDIT (also shows a Rails 2 example)
http://zerowidth.com/2011/03/18/standalone-script-runner-bin-scripts-in-rails.html
Here's the hack I'm using:
rr() {
rails_root="$(bundle exec rails runner "puts Rails.root")"
rp="$(relpath "$1" "$rails_root")"
bundle exec rails runner "eval(File.read '$rp')"
}
relpath() {python -c "import os.path; print os.path.relpath('$1','${2:-$PWD}')";}
Example:
cd ~/rails_project/app/helpers
rr my_script.rb
Based on #moritz's answer here. I changed it, since the working directory for File.read is the Rails project root.
I know this is some serious heresy, using python to help a ruby script. But I couldn't find a relpath method built into ruby.
Credit: relpath() was taken from #MestreLion, Convert absolute path into relative path given a current directory using Bash

Automatically require a class when running / starting ruby

I am doing some monkey patching in some of Ruby classes and I would like that to be included AUTOMATICALLY whenever I run ruby.
For example:
I added the method trim to String. I want to be able to do this:
ruby -e 'puts " aaaa ".trim'
I don't want to do this:
ruby -e 'require "monkey.rb"; puts " aaaa ".trim'
Is there anyway to include my monkey patches evertime I start ruby? How about irb?
Thanks!
ruby and irb both take a -r option that lets you specify a library to load when running those executables. If you want to automatically load your monkey.rb library, you can start ruby with the invocation $ ruby -r monkey (assuming monkey.rb is in your $RUBYLIB path. If you don't want to do that each time, you can set up an alias in your shell config file. For example (in Bash), you could add:
alias ruby='ruby -r monkey'
irb is probably the place where you can do this most simply. When using irb, you can use an initialization file to store anything you want run on every startup. In your home directory ("cd ~"), create a file called ".irbrc", and drop in your "require 'monkey.rb'" statement, that should do it. From then on when you start up irb, it will run anything in that script first.

Resources