Pass ruby script file to rails console - ruby

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

Related

Override "rspec" command to run tests

This seems simple but I can't find a reputable solution via Google or searching SO.
I'm using foreman with a Rails 4 app to load ENV via a .env file. To run my tests properly, I have to execute foreman run rspec [optional files].
This gets tedious and occasionally I forget the foreman run part. I'd like to override the rspec command for a single app so that:
rspec [files] => foreman start [files]
Looked at binstubs but I don't fully understand them and they don't look exactly like what I want.
I can create a bash script that does this, but now that's specific to my local machine instead of built into the app codebase.
I ended up creating a script in my ~/scripts folder (where I store my own scripts added to my PATH).
Here's what I have in ~/scripts/tester (with executable permissions):
#!/bin/bash
#==================================================
# Created: 2014-04-01 / Updated: 2014-04-01
# Desc: Shorten syntax to run tests properly.
#==================================================
# For developers who may not use bash at all...
# $0 = filename and path
# $1 = first arg...
cmd="foreman run rspec $1"
echo "#--------------------------------------------------"
echo "# EXECUTING: $0"
echo "# '$cmd'"
echo "#--------------------------------------------------"
$cmd
I can execute with tester in my rails app directory and it will run foreman run rspec which executes all tests or I can pass in specific files or wildcard-names and it will run the matched tests.
It outputs the file location so if I pass this script on to others they know what files being run so they can modify it...I do this because I've actually run into a situation where a new developer was Googling a "tester" script for rails wondering why he couldn't find it as part of core rails...this way newbies know exactly what's being run and where the file's located at.
Chose tester as the script name because it wouldn't clash with any other known commands AFAIK.
Sample input:
tester => foreman run rspec # all specs
tester spec/models => foreman run rspec spec/models # run all model specs

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`

Issue One command and Run Multiple Ruby Files

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

How to start a brand new process in Rails, without inherit current environment variables?

I'm developing an master rails app which controls other rails apps. It has a bash script to start those rails apps, and it works well while it's invoked in the command line manually.
But if I invoke it in the matter rails app, using backticks, system, or exec, the script will fail.
The error message is:
unicorn_rails worker[0] -c ../configs/unicorns/c5.rb -E production must be run inside RAILS_ROOT:
#<Gem::LoadError: can't activate rack (~> 1.0.0, runtime), already activated rack-1.2.1.
Make sure all dependencies are added to Gemfile.>
And here is the bash file:
cp configs/Gemfile* $1
cd $1
bundle
bundle exec unicorn_rails -c ../configs/unicorns/$1.rb -E production
How to resolve a problem like this?
As you can see, I use bundle exec to start the child process, which should have it's own gems loaded, right?
The environment variables are passed by the OS to Ruby when it loads. Ruby adds its own additional variables, then starts Rails, which adds even more.
You should be able to manipulate them by playing with the ENV hash. This will display what is defined:
ENV.each { |key, val| puts "#{ key } => #{ val }"}
You can tweak what is passed to child processes by directly modifying the ENV values then invoking the code that starts the child:
ENV['PATH'] = '/path/to/application'
ENV['PATH'] # => "/path/to/application"
Modifying the path, or stripping unwanted ENV entries to limit a child app's knowledge of the environment is pretty common.

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