deploy rake task as if it were a common script - ruby

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

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/

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

How to run a ruby script within bundler context?

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.

Gem Development Workflow

I'm working on a fork of someone's gem that is a command line utility. Here's a general overview of the directory structure:
bin/
bin/foo
lib/
lib/foo.rb
lib/foo/bar.rb (etc)
To test it, I normally do something like this:
cd bin/
./foo <args>
But I want to be able to use it from any directory (like it would be once installed). My question is if it's possible to achieve this without installing the gem on my system each time.
My first attempt at this was to create a symbolic link to the foo script that was on my PATH, but this messes with the require 'foo' line in the script since File.dirname(__FILE__) now refers to wherever the symbolic link was created.
Is there a common way of doing this?
(Oh, and here's the relevant lines from the foo script)
#!/usr/bin/env ruby
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
require 'rubygems'
require 'foo'
(EDIT)
I'm aware of the normal ways of testing a library (ie rake test, etc)--I'm specifically interested in using the script from any directory without reinstalling the gem with every change (if possible).
In almost every gem I've looked into, there is a rakefile of some sort. In which case you go to the root of the gem, and go:
rake test
For a list of tasks, use:
rake -T
(This assumes you have rake installed in the first place, obviously: gem install rake if not.)
Also, many a gem also features a gemfile. In this case you can use bundler to install applicable dependencies (in particular, test suites and development-related gems).

How can I write a hook that gets called when a RubyGem is installed?

I'd like to write a Ruby snippet that gets run when my Gem is first installed via [sudo ]gem install mygem. Can it be done?
It doesn't look like it's really supported. I found a "post_install_message" attribute that you should be able to set in the gem spec, but that won't execute code.
You may be able to do it by packaging your on-install code as an extension in your gem (as if it were a native extension), and providing a Rakefile to "build" the extension (i.e. call your code).
I had the same problem. The best solution that I found is as follows:
# your_gem.gemspec
Gem::Specification.new do |spec|
# ...
spec.extensions = ['Rakefile']
end
-
# Rakefile
task :prepare do
# Execute your post-installation code here
end
task default: :prepare
You can try to do this using call of OS commands. I'll quote eample from irb but you can do same in your scripts too.
irb(main):001:0> system 'gem list | grep rails'
rails (2.1.1, 2.1.0)
=> true
irb(main):002:0> system 'gem list | grep railssssss'
=> false
You can use result of this command as the condition of your snippet execution.

Resources