Slide 1

Slide 1 text

BECOMING A RUBY GEMCUTTER

Slide 2

Slide 2 text

i’m @qrush this is @qrush’s dog

Slide 3

Slide 3 text

@ i live here

Slide 4

Slide 4 text

i work at 37signals

Slide 5

Slide 5 text

OMG FIRST CODEMASH!!!

Slide 6

Slide 6 text

RUBY i mostly write

Slide 7

Slide 7 text

RUBY RAILS i mostly write with

Slide 8

Slide 8 text

RUBY GEMS i mostly write inside of

Slide 9

Slide 9 text

RAILS GEMS in fact, is made of

Slide 10

Slide 10 text

GEMS EASY and are

Slide 11

Slide 11 text

EASY!

Slide 12

Slide 12 text

YOU MUST BE THIS CODER TO RIDE THE TALK KNOW A BIT OF RUBY LOVE YOUR CODE WILLING TO LEARN!

Slide 13

Slide 13 text

COVERING: WHAT? HOW? WHY?

Slide 14

Slide 14 text

GEMS GEMS GEMS GEMS GEMS

Slide 15

Slide 15 text

GEMS contain a packaged Ruby library or application.

Slide 16

Slide 16 text

RUBYGEMS helps you download, install, and manipulate gems.

Slide 17

Slide 17 text

RUBYGEMS gives you the gem command

Slide 18

Slide 18 text

RUBYGEMS.ORG is a community repository of gems available for use.

Slide 19

Slide 19 text

RUBYGEMS CLIENT RUBYGEMS.ORG

Slide 20

Slide 20 text

RUBYGEMS CLIENT RUBYGEMS.ORG

Slide 21

Slide 21 text

RUBYGEMS CLIENT RUBYGEMS.ORG .gem .gem

Slide 22

Slide 22 text

http://rubygems.org/pages/download

Slide 23

Slide 23 text

GEM WHAT’S IN A

Slide 24

Slide 24 text

Docs Code Gemspec

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

.GEM RAILS ?

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

RubyGems manages your $LOAD_PATH

Slide 32

Slide 32 text

% 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", "."]

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

RubyGems overrides Kernel#require RubyGems puts bin/ and lib/ on your $LOAD_PATH

Slide 36

Slide 36 text

RubyGems manages your external Ruby code.

Slide 37

Slide 37 text

The Gemspec holds metadata & info about the gem

Slide 38

Slide 38 text

% cat freewill.gemspec Gem::Specification.new do |s| s.name = 'freewill' s.version = '1.0.0' s.date = '2012-01-03' 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

Slide 39

Slide 39 text

A .gem is just a tarball of tarballs

Slide 40

Slide 40 text

% gem fetch rake Downloaded rake-0.8.7 % tar zxvf rake-0.8.7.gem x data.tar.gz x metadata.gz

Slide 41

Slide 41 text

A GEM IS A TARBALL WITHIN A TARBALL

Slide 42

Slide 42 text

WHY CAN’T I USE MY LINUX PACKAGE MANAGER THEN

Slide 43

Slide 43 text

No content

Slide 44

Slide 44 text

LOL, WHAT’S A TARBALL

Slide 45

Slide 45 text

WHY? WHY? WHY? ? WH W HY?

Slide 46

Slide 46 text

Why did you make a RubyGem?

Slide 47

Slide 47 text

REUSE

Slide 48

Slide 48 text

INVENTION

Slide 49

Slide 49 text

AUTOMATION

Slide 50

Slide 50 text

IMPROVEMENT

Slide 51

Slide 51 text

FIX HUGE PROBLEMS

Slide 52

Slide 52 text

GOOD LUCK WITH THAT

Slide 53

Slide 53 text

NO REALLY WHY SHOULD I BOTHER WITH THIS, I’M BUSY! REUSE YOUR CODE EASY TO INSTALL EASY TO SHARE

Slide 54

Slide 54 text

GEM! MAKE YOUR OWN!

Slide 55

Slide 55 text

FIRST GEM EXECUTABLE TESTING DOCS

Slide 56

Slide 56 text

FIRST GEM EXECUTABLE TESTING DOCS

Slide 57

Slide 57 text

% tree . !"" hola.gemspec #"" lib #"" hola.rb

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

require ‘hola’ % tree . !"" hola.gemspec #"" lib #"" hola.rb

Slide 60

Slide 60 text

% cat hola.gemspec Gem::Specification.new do |s| s.name = 'hola' s.version = '0.0.0' s.date = '2011-01-03' 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

Slide 61

Slide 61 text

build install push

Slide 62

Slide 62 text

build install push LOCAL REMOTE

Slide 63

Slide 63 text

% 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

Slide 64

Slide 64 text

SHIP IT!

Slide 65

Slide 65 text

OOPS. bad push?

Slide 66

Slide 66 text

Try your gem out before pushing!

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

At least run your tests first! ...You wrote tests, right?

Slide 69

Slide 69 text

SHIP IT!

Slide 70

Slide 70 text

% 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)

Slide 71

Slide 71 text

REMOTE LOCAL install build push list -r install

Slide 72

Slide 72 text

% gem list -r hola *** REMOTE GEMS *** hola (0.0.0) % gem install hola Successfully installed hola-0.0.0 1 gem installed

Slide 73

Slide 73 text

FIRST GEM EXECUTABLE TESTING DOCS

Slide 74

Slide 74 text

gems are awesome command line tools

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

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

Slide 77

Slide 77 text

% cat bin/hola #!/usr/bin/env ruby require 'hola' puts Hola.hi(ARGV[0])

Slide 78

Slide 78 text

% cat bin/hola #!/usr/bin/env ruby require 'hola' puts Hola.hi(ARGV[0]) (shə-băng')

Slide 79

Slide 79 text

% 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 (shə-băng')

Slide 80

Slide 80 text

% cat bin/hola #!/usr/bin/env ruby require 'hola' puts Hola.hi(ARGV[0]) (shə-băng') “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

Slide 81

Slide 81 text

% ruby -Ilib ./bin/hola Hello world! % ruby -Ilib ./bin/hola CodeMash Hello CodeMash!

Slide 82

Slide 82 text

% ruby -Ilib ./bin/hola Hello world! % ruby -Ilib ./bin/hola CodeMash Hello CodeMash! $LOAD_PATH.unshift(“lib”)

Slide 83

Slide 83 text

% hola Hello world! % hola CodeMash Hello CodeMash!

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

FIRST GEM EXECUTABLE TESTING DOCS

Slide 86

Slide 86 text

outsource your automation and framework

Slide 87

Slide 87 text

automation framework

Slide 88

Slide 88 text

automation framework rake thor

Slide 89

Slide 89 text

automation framework rake thor Test::Unit rspec bacon context matchy shoulda riot testy shindo zebra lemon dfect cucumber steak

Slide 90

Slide 90 text

Test your gem. Use whatever. Please test it.

Slide 91

Slide 91 text

You will be tested: http://test.rubygems.org

Slide 92

Slide 92 text

% cat Rakefile require 'rake/testtask' Rake::TestTask.new do |t| t.libs << 'test' end desc "Run tests" task :default => :test

Slide 93

Slide 93 text

% 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

Slide 94

Slide 94 text

% 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

Slide 95

Slide 95 text

FIRST GEM EXECUTABLE TESTING DOCS

Slide 96

Slide 96 text

Meh.

Slide 97

Slide 97 text

push gem webhook tweet on @rubygems

Slide 98

Slide 98 text

push gem webhook tweet on @rubygems ON EVERY PUSH

Slide 99

Slide 99 text

push gem webhook tweet on @rubygems ON EVERY PUSH ~200+ TIMES DAILY

Slide 100

Slide 100 text

Say hi, your gem will!

Slide 101

Slide 101 text

guides inline

Slide 102

Slide 102 text

guides inline nokogiri yard

Slide 103

Slide 103 text

guides inline nokogiri yard rails datamapper

Slide 104

Slide 104 text

# 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

Slide 105

Slide 105 text

Learn how to document your code: http://yardoc.org

Slide 106

Slide 106 text

10TIPS AWESOME FOR MAKING YOUR GEM

Slide 107

Slide 107 text

Write a README. 1.

Slide 108

Slide 108 text

WHAT SHOULD GO IN A README WHAT IT IS INSTALL INSTRUCTIONS HOW TO USE IT

Slide 109

Slide 109 text

Use a LICENSE 2.

Slide 110

Slide 110 text

Code with no LICENSE is COPYRIGHTED.

Slide 111

Slide 111 text

Pick a license BEFORE pushing your gem.

Slide 112

Slide 112 text

Name your gem properly. 3.

Slide 113

Slide 113 text

DO NOT CALL IT: [rR].* rials cheezburger kitty dicks

Slide 114

Slide 114 text

Have a memorable name, not a stupid one.

Slide 115

Slide 115 text

Have a sane versioning scheme. 4.

Slide 116

Slide 116 text

http://www.flickr.com/photos/ioerror/3014911710/lightbox/

Slide 117

Slide 117 text

3 3.1 3.141 3.1415 3.14159 3.141592 3.14159256

Slide 118

Slide 118 text

http://semver.org Semantic Versioning

Slide 119

Slide 119 text

1.2.3 MAJOR.MINOR.PATCH

Slide 120

Slide 120 text

0.0.X PATCH implementation details small bug fixes

Slide 121

Slide 121 text

0.X.0 MINOR backwards compatible API changes

Slide 122

Slide 122 text

X.0.0 MAJOR backwards incompatible API changes

Slide 123

Slide 123 text

Have one top-level file 5.

Slide 124

Slide 124 text

. #"" lib !"" foo.rb #"" set.rb

Slide 125

Slide 125 text

. #"" lib !"" foo.rb #"" set.rb require ‘set’

Slide 126

Slide 126 text

. #"" lib !"" foo.rb #"" set.rb require ‘set’

Slide 127

Slide 127 text

. #"" lib !"" foo % #"" set.rb #"" foo.rb require ‘foo/set’

Slide 128

Slide 128 text

Don’t mess with $LOAD_PATH 6.

Slide 129

Slide 129 text

. #"" lib !"" hola % #"" translator.rb #"" hola.rb

Slide 130

Slide 130 text

. #"" lib !"" hola % #"" translator.rb #"" hola.rb BAD: require File.join(File.dirname( __FILE__), "hola", "translator")

Slide 131

Slide 131 text

. #"" lib !"" hola % #"" translator.rb #"" hola.rb WORSE: $LOAD_PATH.unshift "lib/hola" require "translator"

Slide 132

Slide 132 text

. #"" lib !"" hola % #"" translator.rb #"" hola.rb GOOD: require "hola/translator"

Slide 133

Slide 133 text

Specify dependencies 7.

Slide 134

Slide 134 text

http://www.slideshare.net/copiousfreetime/gemology

Slide 135

Slide 135 text

runtime development

Slide 136

Slide 136 text

runtime development what your gem needs to work

Slide 137

Slide 137 text

runtime development what your gem needs to work what your tests need to work

Slide 138

Slide 138 text

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"])

Slide 139

Slide 139 text

Be pessimistic (with dependencies) 8.

Slide 140

Slide 140 text

Gem::Specification.new do |s| s.name = "hola" s.version = "2.0.0" s.add_runtime_dependency( "thor", [">= 0.14.5"]) s.add_development_dependency( "rspec", ["= 2.2.0"]) Only this one works for me! EXACT

Slide 141

Slide 141 text

Gem::Specification.new do |s| s.name = "hola" s.version = "2.0.0" s.add_runtime_dependency( "thor", [">= 0.14.5"]) s.add_development_dependency( "rspec", ["= 2.2.0"]) It will always work! OPTIMISTIC

Slide 142

Slide 142 text

Avoid >=

Slide 143

Slide 143 text

Gem::Specification.new do |s| s.name = "hola" s.version = "2.0.0" s.add_runtime_dependency( "thor", [">= 0.14.5", "< 1.0.0"]) s.add_development_dependency( "rspec", ["= 2.2.0"]) Lock to a range instead PESSIMISTIC

Slide 144

Slide 144 text

Gem::Specification.new do |s| s.name = "hola" s.version = "2.0.0" s.add_runtime_dependency( "thor", ["~> 0.14"]) s.add_development_dependency( "rspec", ["= 2.2.0"]) Use the twiddle-wakka! PESSIMISTIC

Slide 145

Slide 145 text

Cut prereleases 9.

Slide 146

Slide 146 text

% head -4 hola.gemspec Gem::Specification.new do |s| s.name = 'hola' s.version = '1.0.0.pre'

Slide 147

Slide 147 text

% head -4 hola.gemspec Gem::Specification.new do |s| s.name = 'hola' s.version = '1.0.0.pre' ANY LETTER(S)

Slide 148

Slide 148 text

% gem install hola --pre Fetching: hola-1.0.0.pre.gem (100%) Successfully installed hola-1.0.0.pre 1 gem installed

Slide 149

Slide 149 text

Build on Travis-CI 10.

Slide 150

Slide 150 text

No configuration, totally free CI. http://travis-ci.org

Slide 151

Slide 151 text

No content

Slide 152

Slide 152 text

GO PUSH A GEM TODAY

Slide 153

Slide 153 text

GO PUSH A GEM TODAY @qrush Thanks!