Today we will create gemsets management stuff and we'll also make Ruby management easier. As previously, lets start from "low-level" bash scripts. Place them somewhere in your app (example: app_root/sript/tasks/rvm) and make them executable (chmod 755).
List available gemsets from a selected Ruby
#!/bin/bash # Returns list of selected ruby gemsets # Requires ruby version as parameter # # Example: ./rvm_gemset_list.sh 1.9.2-p0 die () { echo >&2 "$@" exit 1 } [ "$#" -gt 0 ] || die "Minimum 1 parameter required! $# provided" ruby_version="$1" init_rvm(){ if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then source "$HOME/.rvm/scripts/rvm" elif [[ -s "/usr/local/rvm/scripts/rvm" ]] ; then source "/usr/local/rvm/scripts/rvm" else printf "ERROR: An RVM installation was not found.\n" fi } perform_task(){ init_rvm rvm use $ruby_version > /dev/null rvm gemset list } perform_task
Creating gemset in selected Ruby
#!/bin/bash # Creates gemset in a given Ruby version # Parameters: # 1) Ruby version # 2) Gemset name # # Example: ./rvm_gemset_list.sh 1.9.2-p0 example_gemset die () { echo >&2 "$@" exit 1 } [ "$#" -gt 1 ] || die "Minimum 2 parameters required! $# provided" ruby_version="$1" gemset_name="$2" init_rvm(){ if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then source "$HOME/.rvm/scripts/rvm" elif [[ -s "/usr/local/rvm/scripts/rvm" ]] ; then source "/usr/local/rvm/scripts/rvm" else printf "ERROR: An RVM installation was not found.\n" fi } perform_task(){ init_rvm rvm use $ruby_version > /dev/null rvm gemset create $gemset_name } perform_task
Removing gemset from selected Ruby version
#!/bin/bash # Returns list of selected ruby gemsets # Parameters: # 1) Ruby version # 2) Gemset name # # Example: ./rvm_gemset_list.sh 1.9.2-p0 example_gemset die () { echo >&2 "$@" exit 1 } [ "$#" -gt 0 ] || die "Minimum 1 parameter required! $# provided" ruby_version="$1" gemset_name="$2" init_rvm(){ if [[ -s "$HOME/.rvm/scripts/rvm" ]] ; then source "$HOME/.rvm/scripts/rvm" elif [[ -s "/usr/local/rvm/scripts/rvm" ]] ; then source "/usr/local/rvm/scripts/rvm" else printf "ERROR: An RVM installation was not found.\n" fi } perform_task(){ init_rvm rvm use $ruby_version > /dev/null rvm --force gemset delete $gemset_name } perform_task
Creating RVM class
Ok, so we can now install/uninstall Rubies and create/destroy gemsets. Let's wrap it with some Ruby magic! We'll start from creating RVM class. It will represent RVM in our application:
class RVM class RVMNotInstalled < StandardError; end # Check if RVM is installed def self.installed? c = Script.new('rvm/list') res = c.run !res.include?('nie znale') && !res.include?('not f') rescue false end def self.check_for_rvm raise RVMNotInstalled unless self.installed? end end
If RVM is not installed running list script will return something like "command not found". Thanks to this, we can check whether or not RVM is installed.
Let's make things better!
Ok, now the better stuff. Ruby stuff :) Each Ruby instance should have it's own representation in our application (not in AR - will wrap it with AR in next part of this tutorial):
class RVM class Ruby class UnknownRubyVersion < StandardError; end class GemsetAlreadyExists < StandardError; end class GemsetDoesNotExist < StandardError; end class RubyVersionAlreadyInstalled < StandardError; end attr_reader :version attr_accessor :gemset end end
Exceptions description:
- UnknownRubyVersion - will be raised when trying ti install/uninstall unknown (not existing) Ruby version
- GemsetAlreadyExists - when trying to install gemset which already exists
- GemsetDoesNotExist - when trying to remove non existing gemset
- RubyVersionAlreadyInstalled - when trying to install already installed Ruby version
Install/Uninstall Ruby
Now methods from RVM::Ruby:
class RVM class Ruby def self.install(ruby, log_path, lock_id) raise RubyVersionAlreadyInstalled, ruby if self.list.include?(ruby) raise UnknownRubyVersion, ruby unless self.known.include?(ruby) c = Script.new('rvm/install', ruby, log_path, lock_id) c.ignite end def self.uninstall(ruby, log_path) raise UnknownRubyVersion, ruby unless self.list.include?(ruby) c = Script.new('rvm/uninstall', ruby, log_path) c.run end end end
Other helpful class methods
class RVM class Ruby def self.selected RVM.check_for_rvm c = Script.new('rvm/list') list = c.run #list.delete!('rvm rubies') list = list.split("\n") selected = false list.each do |ruby| selected = ruby.delete('=> ').strip if ruby.include?('=> ') end selected.split('[').first end # Returns list of rvm rubies installed def self.list RVM.check_for_rvm c = Script.new('rvm/list') list = c.run #list.delete!('rvm rubies') list = list.split("\n") rubies = [] list.each do |ruby| ruby = ruby.delete('=> ').strip next if ruby == 'rvmrubies' || ruby == "" rubies << ruby.split('[').first end rubies end # Returns list of known rubies def self.known RVM.check_for_rvm c = Script.new('rvm/known') list = c.run rubies = [] list.split("\n").each do |r| next if r.include?('#') next if r.include?('iron') next if r.include?('macruby') next if r == '' r+='-head' unless r.include?('-') rubies << r.strip.delete('[').delete(']') end rubies end end end
RVM::Ruby Instance methods
Ok, so now we have a bunch of useful class methods, however we still cannot manipulate on a single Ruby instance stuff such as gemsets. But, not for long. Lets start with initialization of an RVM::Ruby instance:
def initialize(ruby, gemset = nil) RVM.check_for_rvm @version = ruby @gemset = gemset raise UnknownRubyVersion, ruby unless self.class.list.include?(ruby) if @gemset raise GemsetDoesNotExist, @gemset unless gemsets.include?(@gemset) end end
Now it is time for gemsets management:
# Show all gemsets available in this ruby version def gemsets c = Script.new("rvm/gemsets", version) list = c.run list = list.split("\n") gemsets = [] list[1..-1].each do |g| next if g.include?('gemsets for') g.delete!('=> ') gemsets << g.strip end gemsets end def gemset_selected unless @gemset c = Script.new("/rvm/gemsets", version) list = c.run list = list.split("\n") selected = nil list[1..-1].each do |g| next if g.include?('gemsets for') selected = g.strip if g.include?('=> ') end @gemset = selected end @gemset end def create_gemset(name) raise GemsetAlreadyExists, name if gemsets.include?(name) c = Script.new("rvm/gemset_create", version, name) c.run true end def delete_gemset(name) raise GemsetDoesNotExist, name unless gemsets.include?(name) c = Script.new("rvm/gemset_delete", version, name) c.run true end
and one additional method:
def full_name "#{version}@#{gemset}" end
That's all for now! Managing RVM stuff now is much easier, for example we can do something like this:
RVM::Ruby.install('ruby-1.9.2-head', '/var/log/ruby_install.log', 1234) # wait till installation ends ruby = RVM::Ruby.new('ruby-1.9.2-head') ruby.create_gemset('my_gemset')