How to run a ruby script within bundler context? - ruby

I have a Ruby script called foo.rb, and I want to run it within the context of the bundler environment. How?
bundle exec foo.rb doesn't work, because exec expects a shell script.

Pass the script name to the ruby command:
bundle exec ruby script_name
If you also want the Rails environment:
bundle exec rails runner script_name

For instance, I wanted to use the same version of Rubocop as my Rails app and not the latest system one, so doing this in a script:
require 'bundler'
Bundler.require
# ...
Allowed me to use my app's version of rubocop.

You can just make it a script - add
#!/usr/bin/env ruby
to the start of the file, and make it executable. Then bundle exec foo.rb will work as expected.
(This is on unix or OSX - not sure about Windows)
See http://bundler.io/v1.15/man/bundle-exec.1.html#Loading
Also see https://coderwall.com/p/kfyzcw/execute-ruby-scripts-directly-without-bundler-exec for how to run ruby scripts with bundled dependencies, without needing bundle exec

If you want to create a script that you can run in bundle context within a project, you can invoke Bundler programmatically. E.g., given a project:
foo
├── Gemfile
└── bar
└── baz.rb
you can put the following at the top of baz.rb to give it access to the gems in the Gemfile:
#!/usr/bin/env ruby
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
require 'bundler/setup'
# ...etc.
With that, you can invoke the script directly without using bundle exec, and you also don't have to invoke it from within the project directory.

Related

Require files from gem in Ruby script without bundle exec

I have a script that needs to require specific files out of gems defined in the project Gemfile.
#!/usr/bin/env ruby
require 'some_gem/helpers/some_helper'
... rest of script
When I run the script, I get an error about not being able to load some_helper.rb. If I run with bundle exec command... then everything works.
I understand that bundle exec exposes the Gems to the $LOAD_PATH which lets require work. Is there a way to move that capability into the script so users don't have to type bundle exec?
Do I just need to add require "bundler/setup" to the script before I require the gem files?
http://bundler.io/v1.12/#getting-started
:)
#!/usr/bin/env ruby
require 'rubygems' # because reasons.. most probably it is not needed unless you are using really old ruby where it is not loaded by default
# also at the moment rubygems and bundler are being merged :)
require 'bundler/setup' # for things installed with bundler
require 'some_gem/helpers/some_helper'
You can also check e.g. http://mislav.net/2013/01/understanding-binstubs/

Run gem from local source code

I am currently working on developing a gem and I would like to be able to run that gem from command line and point it to my local source. Previously I've done this in rails by specifying the path in the gem file but now I would like to run the gem on a non rails app. So I would like to know how to call the gem from command line and specify that I want to use the source code in a certain directory.
For example can I cd into the directory that I want to run it on and do something like: ruby my_gem --path=~/code/mygem
Also do I have to build them gem or can I run it from source without building it?
From the root directory of your gem, try this to execute lib/MyGem.rb:
ruby -Ilib lib/MyGem.rb
or test your gem interactive:
irb -Ilib
> require 'mygem'
true

Execute without `bundle exec` via rubygems-bundler

I have a standard gem scaffold, and in inside the bin directory I have a simple executable (bin/do_things.rb):
#!/usr/bin/env ruby
require 'my_gem'
MyGem::doThings()
The gem hasn't been installed via gem install, so running bin/do_things.rb without bundle exec fails (my Gemfile has the gemspec line in it).
Is there a simple way to have rubygems-bundler execute my script in the bundler context? Should I just modify the $LOAD_PATH in my executable instead?
I could create a wrapper script to execute under Bundler as well, but I'd rather leverage rubygems-bundler somehow.
Or should I just type bundle exec?
try:
bundle exec bash -l
it will set you into bundler context - it's an extra shell so running exit will get you back to bundler less context.
Change the file permission
chmod a+x bin/do_things.rb
and resolve bin path, ignoring symlinks
require "pathname"
bin_file = Pathname.new(__FILE__).realpath
post, add self to libpath
$:.unshift File.expand_path("../../lib", bin_file)
Generating binstubs via bundle install --binstubs creates a wrapper script for all executables listed in my gemspec.
#!/usr/bin/env ruby
#
# This file was generated by Bundler.
#
# The application 'do_things.rb' is installed as part of a gem, and
# this file is here to facilitate running it.
#
require 'pathname'
ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
Pathname.new(__FILE__).realpath)
require 'rubygems'
require 'bundler/setup'
load Gem.bin_path('my_gem', 'do_things.rb')
However, by default, the binstubs path is bin, which conflicts with gem's executable path, and will overwrite files in bin.
Running bundle install --binstubs=SOME_DIR and then adding SOME_DIR to .gitignore seem to be the most maintainable way.
Then, I can simple execute SOME_DIR/do_things or any other project-specific executable I add down the line.

Is it possible to use 'bundle exec' functionality from code?

I'm building a web interface to a few tools and I'd like to be able to run commands or gems within a Bundler context, like the 'bundle exec' command does, except from within my code.
So usually, I'd write on the command line:
bundle exec rspec
Is there a way I can achieve the same thing, but programatically?
If you want to run some ruby with bundled gems you can just require "bundler/setup":
require 'bundler/setup'
require 'rspec' # loads the version specified in Gemfile
You can wrap shell commands in backticks (`) in Ruby.
def run_specs
`bundle exec rspec | grep foo`
end

deploy rake task as if it were a common script

I like the rake task structure and rake utilities.. I want to create a script that can do many things, and rake seems the logical choice.
I want to know how can I make it look like a regular script:
./myscript.rb cake:bake
as opposed to
rake -f myscript.rb cake:bake
any idea? Of course, rake must still be installed etc.. simply to make it easier to use...
myscript.rb:
#!/usr/bin/ruby
require 'rubygems'
require 'rake'
namespace :cake do
task :bake do
puts "Baking cake..."
end
end
Rake::Task[ARGV.first].execute
Then on the command line:
chmod +x myscript.rb
./myscript.rb cake:bake
I found this for cygwin / windows
http://errtheblog.com/posts/60-sake-bomb
removes the dependency on rails and let's you have rake tasks installed and available globally

Resources