You are on page 1of 131

cutting your own RubyGems

R B Y
Nick Quaranto
@qrush nick@thoughtbot.com
Wednesday, May 25, 2011
first, a

P S A
Wednesday, May 25, 2011
Where have all of
the manuals gone?

Wednesday, May 25, 2011


http://history.nasa.gov/diagrams/gemini.html
Wednesday, May 25, 2011
http://history.nasa.gov/diagrams/gemini.html
Wednesday, May 25, 2011
http://archive.computerhistory.org/resources/text/Apple/Apple.AppleI.1976.102646518.pdf
Wednesday, May 25, 2011
http://archive.computerhistory.org/resources/text/Apple/Apple.AppleI.1976.102646518.pdf
Wednesday, May 25, 2011
http://archive.computerhistory.org/resources/text/Apple/Apple.AppleI.1976.102646518.pdf
Wednesday, May 25, 2011
http://archive.computerhistory.org/resources/text/Apple/Apple.AppleI.1976.102646518.pdf
Wednesday, May 25, 2011
http://ed-thelen.org/comp-hist/CRAY-1-HardRefMan/CRAY-1-HRM.html
Wednesday, May 25, 2011
http://ed-thelen.org/comp-hist/CRAY-1-HardRefMan/CRAY-1-HRM.html
Wednesday, May 25, 2011
http://ed-thelen.org/comp-hist/CRAY-1-HardRefMan/CRAY-1-HRM.html
Wednesday, May 25, 2011
http://guides.rubyonrails.org

Wednesday, May 25, 2011


http://progit.org

Wednesday, May 25, 2011


http://guides.sproutcore.org

Wednesday, May 25, 2011


We need
MORE
manuals!

Wednesday, May 25, 2011


MAKE
MANUALS
Wednesday, May 25, 2011
http://guides.rubygems.org

Wednesday, May 25, 2011


what is a gem?

G E M
Wednesday, May 25, 2011
Gems contain a
packaged Ruby
application or library.

Wednesday, May 25, 2011


RubyGems helps you
download, install, and
mani pulate gems.

Wednesday, May 25, 2011


rubygems.org
rubygems client

Wednesday, May 25, 2011


rubygems.org
rubygems client

gems

Wednesday, May 25, 2011


gems,
gemspecs,
indexes
from S3
rubygems.org
rubygems client

gems

Wednesday, May 25, 2011


.gem

Wednesday, May 25, 2011


Docs Code Gemspec

Wednesday, May 25, 2011


% tree freewill
freewill/
|-- bin/
| `-- freewill
|-- lib/
| `-- freewill.rb
|-- test/
| `-- test_freewill.rb
|-- README
|-- Rakefile
`-- freewill.gemspec

Wednesday, May 25, 2011


???

.gem Rails

Wednesday, May 25, 2011


Ruby looks on your
$LOAD_PATH when
you call Kernel#require

Wednesday, May 25, 2011


RubyGems manages
your $LOAD_PATH

Wednesday, May 25, 2011


% irb -rpp
>> pp $LOAD_PATH
[".../lib/ruby/site_ruby/1.8",
".../lib/ruby/site_ruby",
".../lib/ruby/vendor_ruby/1.8",
".../lib/ruby/vendor_ruby",
".../lib/ruby/1.8",
"."]

Wednesday, May 25, 2011


% irb -rpp
>> require 'rake'
LoadError: no such file to load --
rake
from (irb):2:in `require'
from (irb):2

Wednesday, May 25, 2011


>> require 'rubygems'
=> true
>> require 'rake'
=> true
>> pp $LOAD_PATH[0..1]
[".../gems/rake-0.8.7/bin",
".../gems/rake-0.8.7/lib"]

Wednesday, May 25, 2011


RubyGems overrides
Kernel#require

RubyGems puts bin/ and


lib/ on your $LOAD_PATH

Wednesday, May 25, 2011


Gemspec holds
metadata & info
about the gem

Wednesday, May 25, 2011


% cat freewill.gemspec
Gem::Specification.new do |s|
s.name = 'freewill'
s.version = '1.0.0'
s.date = '2010-04-27'
s.summary = "Freewill!"
s.description = "I will choose Freewill!"
s.authors = ["Nick Quaranto"]
s.email = 'nick@quaran.to'
s.homepage = 'http://example.com'
s.files = ["lib/freewill.rb"]
end

Wednesday, May 25, 2011


A gem is just
a tarball of
tarballs

Wednesday, May 25, 2011


% gem fetch rake
Downloaded rake-0.8.7

% tar zxvf rake-0.8.7.gem


x data.tar.gz
x metadata.gz

Wednesday, May 25, 2011


A GEM IS A TARBALL
WITHIN A TARBALL
Wednesday, May 25, 2011
WHY CAN’T I USE
MY LINUX PACKAGE
MANAGER THEN

Wednesday, May 25, 2011


Wednesday, May 25, 2011
LOL, WHAT’S A TARBALL

Wednesday, May 25, 2011


make your own gem

D Y I
Wednesday, May 25, 2011
share/modularize code
automate your process
releasing a gem is easy!

Wednesday, May 25, 2011


first gem

Wednesday, May 25, 2011


Your gem
needs a name

Wednesday, May 25, 2011


DO NOT CALL IT:
[rR].*
rials
cheezburger
kitty
dicks
Wednesday, May 25, 2011
no capitals, please
use underscores for spaces
use dashes for extensions

Wednesday, May 25, 2011


% tree
.
├── hola.gemspec
└── lib
└── hola.rb

Wednesday, May 25, 2011


% cat lib/hola.rb
class Hola
def self.hi(msg = "world")
puts "Hello #{msg}!"
end
end

Wednesday, May 25, 2011


require ‘hola’

% tree
.
├── hola.gemspec
└── lib
└── hola.rb
Wednesday, May 25, 2011
% cat hola.gemspec
Gem::Specification.new do |s|
s.name = 'hola'
s.version = '0.0.0'
s.date = '2010-04-28'
s.summary = "Hola!"
s.description = "A simple hello world gem"
s.authors = ["Nick Quaranto"]
s.email = 'nick@quaran.to'
s.files = ["lib/hola.rb"]
s.homepage =
'http://rubygems.org/gems/hola'
end

Wednesday, May 25, 2011


build

install

push
Wednesday, May 25, 2011
build

LOCAL

install

push
Wednesday, May 25, 2011
build

LOCAL

install

REMOTE
push
Wednesday, May 25, 2011
% gem build hola.gemspec
Successfully built RubyGem
Name: hola
Version: 0.0.0
File: hola-0.0.0.gem

% gem install ./hola-0.0.0.gem


Successfully installed hola-0.0.0
1 gem installed

Wednesday, May 25, 2011


Wednesday, May 25, 2011
Wednesday, May 25, 2011
try your gem out
before pushing!

Wednesday, May 25, 2011


% irb -rubygems
>> require 'hola'
=> true
>> Hola.hi
Hello world!

Wednesday, May 25, 2011


require 'ubygems.rb'

% irb -rubygems
>> require 'hola'
=> true
>> Hola.hi
Hello world!

Wednesday, May 25, 2011


Wednesday, May 25, 2011
% gem push hola-0.0.0.gem
Enter your RubyGems.org credentials.
Don't have an account yet?
Create one at http://rubygems.org/sign_up
Email: nick@quaran.to
Password:
Signed in.
Pushing gem to RubyGems.org...
Successfully registered gem: hola (0.0.0)

Wednesday, May 25, 2011


build

LOCAL
install

push
REMOTE

install list -r
Wednesday, May 25, 2011
% gem list -r hola

*** REMOTE GEMS ***

hola (0.0.0)

% gem install hola


Successfully installed hola-0.0.0
1 gem installed

Wednesday, May 25, 2011


first gem

executable

Wednesday, May 25, 2011


gems are like
awesome shell aliases

Wednesday, May 25, 2011


% curl -s http://jsonip.com/ | \
prettify_json.rb
{
"ip": "24.60.248.134"
}

Wednesday, May 25, 2011


% mkdir bin
% touch bin/hola
% chmod a+x bin/hola

Wednesday, May 25, 2011


% cat bin/hola
#!/usr/bin/env ruby

require 'hola'
puts Hola.hi(ARGV[0])

Wednesday, May 25, 2011


(shə-băng')

% cat bin/hola
#!/usr/bin/env ruby

require 'hola'
puts Hola.hi(ARGV[0])

Wednesday, May 25, 2011


(shə-băng')

% cat bin/hola
#!/usr/bin/env ruby

require 'hola'
puts Hola.hi(ARGV[0])
“Probably derived from “shell bang” under the influence of
American slang “the whole shebang” (everything, the works)”
http://www.retrologic.com/jargon/S/shebang.html
Wednesday, May 25, 2011
(shə-băng')

% cat bin/hola
#!/usr/bin/env ruby

require 'hola'
puts Hola.hi(ARGV[0])
“Probably derived from “shell bang” under the influence of
American slang “the whole shebang” (everything, the works)”
http://www.retrologic.com/jargon/S/shebang.html
Wednesday, May 25, 2011
% ruby -Ilib ./bin/hola
Hello world!

% ruby -Ilib ./bin/hola Baltimore


Hello Baltimore!

Wednesday, May 25, 2011


$LOAD_PATH.unshift(“lib”)

% ruby -Ilib ./bin/hola


Hello world!

% ruby -Ilib ./bin/hola Baltimore


Hello Baltimore!

Wednesday, May 25, 2011


% hola
Hello world!

% hola Baltimore
Hello Baltimore!

Wednesday, May 25, 2011


% head -4 hola.gemspec
Gem::Specification.new do |s|
s.name = 'hola'
s.version = '0.0.1'
s.executables << 'hola'

Wednesday, May 25, 2011


first gem

executable

tests

Wednesday, May 25, 2011


automation framework

Wednesday, May 25, 2011


automation framework

rake
thor
Wednesday, May 25, 2011
automation framework
Test::Unit rspec
rake bacon context
matchy shoulda
riot testy shindo
thor zebra lemon dfect
cucumber steak
Wednesday, May 25, 2011
Test your gem.
Use whatever.
Please test it.

Wednesday, May 25, 2011


http://test.rubygems.org

Wednesday, May 25, 2011


Wednesday, May 25, 2011
% cat Rakefile
require 'rake/testtask'

Rake::TestTask.new do |t|
t.libs << 'test'
end

desc "Run tests"


task :default => :test

Wednesday, May 25, 2011


% cat test/test_hola.rb
require 'test/unit'
require 'hola'

class HolaTest < Test::Unit::TestCase


def test_default_hello
assert_equal "Hello world!",
Hola.hi
end

def test_custom_hello
assert_equal "Hello Boston!",
Hola.hi("Boston")
end
end
Wednesday, May 25, 2011
% rake test
(in /Users/qrush/Dev/ruby/hola)
Loaded suite
Started
..
Finished in 0.000736 seconds.

2 tests, 2 assertions, 0 failures,


0 errors, 0 skips

Test run options: --seed 15331

Wednesday, May 25, 2011


first gem

executable

tests

docs
Wednesday, May 25, 2011
Others will use your gem.
Write about it.

Wednesday, May 25, 2011


At least have a README!

Wednesday, May 25, 2011


http://twitter.com/rubygems
Wednesday, May 25, 2011
guides inline

Wednesday, May 25, 2011


guides inline

nokogiri
yard
Wednesday, May 25, 2011
guides inline

nokogiri rails
yard datamapper
Wednesday, May 25, 2011
# The main Hola driver
class Hola
# Say hi to the world!
#
# Example:
# >> Hola.hi("Buffalo")
# => Hello Buffalo!
#
# Arguments:
# message: (String)

def self.hi(message = "world")


puts "Hello #{message}!"
end
end

Wednesday, May 25, 2011


Wednesday, May 25, 2011
http://yardoc.org
patterns

P T N
Wednesday, May 25, 2011
more files

Wednesday, May 25, 2011


.
└── lib
   ├── hola
   │   └── translator.rb
   └── hola.rb

Wednesday, May 25, 2011


.
└── lib
   ├── hola
   │   └── translator.rb
   └── hola.rb
BAD:
require File.join(File.dirname(
__FILE__), "hola", "translator")

Wednesday, May 25, 2011


.
└── lib
   ├── hola
   │   └── translator.rb
   └── hola.rb
WORSE:
$LOAD_PATH.unshift "lib/hola"
require "translator"

Wednesday, May 25, 2011


.
└── lib
   ├── hola
   │   └── translator.rb
   └── hola.rb
GOOD:
require "hola/translator"

Wednesday, May 25, 2011


Keep only one
top-level file in lib/

Wednesday, May 25, 2011


.
└── lib
   ├── foo
   │   └── cgi.rb
   ├── foo.rb
   └── set.rb

Wednesday, May 25, 2011


.
└── lib
   ├── foo
   │   └── cgi.rb
   ├── foo.rb
   └── set.rb

require ‘set’
Wednesday, May 25, 2011
.
└── lib
   ├── foo
   │   └── cgi.rb
   ├── foo.rb
   └── set.rb

require ‘foo/cgi’
Wednesday, May 25, 2011
more files

semver

Wednesday, May 25, 2011


Have a sane
versioning scheme

Wednesday, May 25, 2011


http://www.flickr.com/photos/ioerror/3014911710/lightbox/
Wednesday, May 25, 2011
3
3.1
3.14
3.141
3.1415
3.14159
3.141592
3.1415926
Wednesday, May 25, 2011
http://semver.org

Wednesday, May 25, 2011


1.2.3

MAJOR.MINOR.PATCH

Wednesday, May 25, 2011


0.0.x
PATCH
implementation details
small bug fixes
Wednesday, May 25, 2011
0.x.0
MINOR
backwards compatible
API changes
Wednesday, May 25, 2011
x.0.0
MAJOR
backwards incompatible
API changes
Wednesday, May 25, 2011
more files

semver

dependencies

Wednesday, May 25, 2011


http://www.slideshare.net/copiousfreetime/gemology
Wednesday, May 25, 2011
Specify your
dependencies

Wednesday, May 25, 2011


runtime development

Wednesday, May 25, 2011


runtime development
what your
gem
needs to
work
Wednesday, May 25, 2011
runtime development
what your what your
gem tests
needs to need to
work work
Wednesday, May 25, 2011
Gem::Specification.new do |s|
s.name = "hola"
s.version = "2.0.0"
s.add_runtime_dependency(
"daemons", ["= 1.1.0"])
s.add_development_dependency(
"rspec", [">= 2.2.0"])

Wednesday, May 25, 2011


Avoid >=

Wednesday, May 25, 2011


Gem::Specification.new do |s|
s.name = "hola"
s.version = "2.0.0"
s.add_runtime_dependency(
"daemons", ["= 1.1.0"])
s.add_development_dependency(
"rspec", [">= 2.0.0"])

Exact
This one works for me!
Wednesday, May 25, 2011
Gem::Specification.new do |s|
s.name = "hola"
s.version = "2.0.0"
s.add_runtime_dependency(
"daemons", ["= 1.1.0"])
s.add_development_dependency(
"rspec", [">= 2.2.0"])

Optimistic
Wednesday, May 25, 2011
It will always work!
Gem::Specification.new do |s|
s.name = "hola"
s.version = "2.0.0"
s.add_runtime_dependency(
"daemons", ["= 1.1.0"])
s.add_development_dependency(
"rspec", [">= 2.2.0", "< 3.0.0"])

Pessimistic
This and future minor releases work
Wednesday, May 25, 2011
Gem::Specification.new do |s|
s.name = "hola"
s.version = "2.0.0"
s.add_runtime_dependency(
"daemons", ["= 1.1.0"])
s.add_development_dependency(
"rspec", ["~> 2.2"])

Pessimistic
Use the twiddle-wakka!
Wednesday, May 25, 2011
releasing a gem
is easy!

Wednesday, May 25, 2011


have a sane
versioning scheme

Wednesday, May 25, 2011


MAKE
MANUALS
Wednesday, May 25, 2011
Thanks for listening!

T H X
http://guides.rubygems.org

Big thanks to:


thoughtbot Nick Quaranto
Jeremy Hinegardner @qrush nick@thoughtbot.com
Wednesday, May 25, 2011

You might also like