Rubygems And You

Post on 15-Jan-2015

2.436 views 1 download

Tags:

description

RubyGems are the packaging system used by Ruby to distribute libraries. What people forget is that it’s pretty easy to make and distribute your own gems. This talk will cover the basics of creating and managing a RubyGem using Rake and GitHub. Jeweler, a tool for automating these tasks, will also be covered.

Transcript of Rubygems And You

Josh Nichols technicalpickles.com

RubyGems and You

Josh Nichols technicalpickles.com

• How ‘require’ works

• Where rubygems fits in

• Creating your own rubygem from scratch

• Creating your own rubygem using jeweler

Overview

Josh Nichols technicalpickles.com

•How ‘require’ works

• Where rubygems fits in

• Creating your own rubygem from scratch

• Creating your own rubygem using jeweler

Overview

Josh Nichols technicalpickles.com

executes the contents of a file

require

Josh Nichols technicalpickles.com

# foo.rbputs "zomg, so awesome"

# bar.rbrequire 'foo.rb'

$ ruby bar.rbzomg, so awesome

Josh Nichols technicalpickles.com

absolute path

require ‘/usr/lib/awesome.rb’

Josh Nichols technicalpickles.com

relative path

require ‘subdir/foo.rb’

Josh Nichols technicalpickles.com

can omit the .rb

require ‘subdir/foo’

Josh Nichols technicalpickles.com

list of directories to look for required files

$LOAD_PATH

Josh Nichols technicalpickles.com

$LOAD_PATH includes your ruby install....this actually lives under a path like:

/usr/local/lib/ruby/1.8/

require ‘net/http’

Josh Nichols technicalpickles.com

only will execute a particular path once

require

Josh Nichols technicalpickles.com

# foo.rbputs "zomg, so awesome"

# bar.rbrequire 'foo'require 'foo'require './foo'

$ ruby bar.rbzomg, so awesomezomg, so awesome

Josh Nichols technicalpickles.com

• Different environments (mac vs. win. vs. linux)

• People install stuff to random places

• Different versions of libraries

• What do we do?

Dealing with diversity...

Josh Nichols technicalpickles.com

MASS HYSTERIA!

Josh Nichols technicalpickles.com

• How ‘require’ works

•Where rubygems fits in

• Creating your own rubygem from scratch

• Creating your own rubygem using jeweler

Overview

Josh Nichols technicalpickles.com

• Handles downloading and installing library

• Manages $LOAD_PATH

• Allows a developer to package & distribute their library

Enter RubyGems

Josh Nichols technicalpickles.com

• gem install burninator

Installing

Josh Nichols technicalpickles.com

Using gems

require 'rubygems'require 'burninator'

Josh Nichols technicalpickles.com

Using gems in under Rails

# config/environment.rb, or anywhere reallyrequire 'burninator'

Josh Nichols technicalpickles.com

Using gems in under Rails

# config/environment.rbconfig.gem 'burninator'

Josh Nichols technicalpickles.com

Using gems in under Rails

# create vendor/gems...# then 'gem unpack' gems there# config/environment.rbRails::Initializer.run do |config| config.load_paths += Dir["#{RAILS_ROOT}/vendor/gems/**"].map do |dir| File.directory?(lib = "#{dir}/lib") ? lib : dir endend

Josh Nichols technicalpickles.com

Where do gems live?

Josh Nichols technicalpickles.com

• RubyGems already knows about it by default

• Has been the defacto standard for hosting

Josh Nichols technicalpickles.com

• But you need to apply for projects...

• And you need extra tools to publish gems...

Josh Nichols technicalpickles.com

• The new hotness

• Just create a repository and turn on RubyGem support

• Create a Gem::Specification, and push it

Josh Nichols technicalpickles.com

• How ‘require’ works

• Where rubygems fits in

•Creating your own rubygem from scratch

• Creating your own rubygem using jeweler

Overview

Josh Nichols technicalpickles.com

• Rake for automation

• Testing framework of choice (we’ll assume test/unit)

• RubyGems

Tools of the trade

Josh Nichols technicalpickles.com

Directory Layout

|~bin/| `-cylon_detector|~lib/| `-cylon_detector.rb|~test/| |-test_cylon_detector.rb| `-test_helper.rb|-LICENSE|-Rakefile`-README.rdoc

Josh Nichols technicalpickles.com

Rakefile basics

require 'rubygems'require 'rake'

Josh Nichols technicalpickles.com

• Metadata about your gem

• name, files, binaries, homepage, etc, etc

Gem::Specification

Josh Nichols technicalpickles.com

Rakefile gemspecspec = Gem::Specification.new do |s| s.name = 'cylon-detector' s.version = '0.8.1' s.authors = ['Josh Nichols'] s.date = '2009-02-03' s.email = 'josh@technicalpickles.com' s.files = FileList['{bin,lib}/**'] s.executables = 'cylon_detector' s.has_rdoc = true s.summary = 'Detect cylons with ease'end

Josh Nichols technicalpickles.com

Rakefile gemspec

task :gemspec do File.open('cylon-detector.gemspec', 'w') do |file| file.write spec.to_ruby endend

Josh Nichols technicalpickles.com

Rakefile package

require 'rake/gempackagetask'Rake::GemPackageTask.new(spec) do |pkg| pkg.need_zip = false pkg.need_tar = falseend

Josh Nichols technicalpickles.com

Rakefile rdoc

require 'rake/rdoctask'Rake::RDocTask.new do |rdoc| rdoc.rdoc_dir = 'rdoc' rdoc.title = 'cylon-detector' rdoc.options << '--line-numbers' << '--inline-source' rdoc.rdoc_files.include('README.rdoc') rdoc.rdoc_files.include('lib/**/*.rb')end

Josh Nichols technicalpickles.com

Rakefile test

require 'rake/testtask'Rake::TestTask.new(:test) do |t| t.test_files = 'test/**/test_*.rb' t.verbose = falseend

Josh Nichols technicalpickles.com

Rakefile rcov

begin require 'rcov/rcovtask' Rcov::RcovTask.new do |t| t.test_files = 'test/**/test_*.rb' t.verbose = true endrescue LoadError task :rcov do abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov" endend

Josh Nichols technicalpickles.com

Rakefile default

task :default => :test

Josh Nichols technicalpickles.com

bin/cylon_detector

#!/usr/bin/env ruby

$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))require 'cylon_detector'

# detection code here

Josh Nichols technicalpickles.com

• The entry point into your library

• Require all dependencies (internal and external)

• Design decisions

• generally want to namespace your project

• class or module?

• Do not require rubygems (unless you are interacting directly with it)

lib/cylon_detector.rb

Josh Nichols technicalpickles.com

• Central location to setup testing environment

test/test_helper.rb

require 'rubygems'require 'test/unit'

$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))$LOAD_PATH.unshift(File.dirname(__FILE__))

require 'cylon_detector'

class Test::Unit::TestCaseend

Josh Nichols technicalpickles.com

test/test_cylon_detector.rb

require File.dirname(__FILE__) + '/test_helper'

class CylonDetectorTest < Test::Unit::TestCase # tests go hereend

Josh Nichols technicalpickles.com

• Hack and commit your code

• ‘rake gemspec’ and commit your gemspec

• push to GitHub

• wait for the gem to build

• rejoice and have some Scotch

Workflow

Josh Nichols technicalpickles.com

• How ‘require’ works

• Where rubygems fits in

• Creating your own rubygem from scratch

•Creating your own rubygem using jeweler

Overview

Josh Nichols technicalpickles.com

• Handles the grunt work

• Generator

• Skeleton project setup for your test framework of choice

• Starts a git repo setup for GitHub

• Creates the repo on GitHub and enables RubyGem for it

• Rake tasks

• Automate version bumping

• Releasing to GitHub, including tagging the release

Jeweler

Josh Nichols technicalpickles.com

• Choose between testing frameworks

• Test::Unit

• Shoulda

• RSpec

• Bacon

• Also includes cucumber stories enabled for

Generator

Josh Nichols technicalpickles.com

• Tracks current version in VERSION.yml

• Rake tasks for bumping the version

• version:bump:patch, version:bump:minor, version:bump:major

Versioning

Josh Nichols technicalpickles.com

patch versionAPI backward-compatible

bug fixesminor enhancements

0.8.5

Josh Nichols technicalpickles.com

minor versionmostly API backwards compatiblemore significant enhancements

0.8.5

Josh Nichols technicalpickles.com

major versionbreak API as much you wantusually signifies an overhaul

0.8.5

Josh Nichols technicalpickles.com

• Updates the gemspec based on the version

• Pushes to GitHub

• Tags the release with the version number

Releasing