Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Cutting your own RubyGems

Cutting your own RubyGems

Diving head-first into RubyGems is rough: there’s a myriad of documentation sites, blog posts, screencasts, and manpages to read, and it’s tough to find “the” guide on how to publish your first RubyGem. In this session you’ll learn why making them is important for your Rails application’s maintainability and how distributing your code in gems even internally is helpful. You’ll find out what happens from “gem push” to “gem install”, and how Rails’ engine system makes sharing application and business logic easy.

Given at RailsConf 2011. http://en.oreilly.com/rails2011

Nick Quaranto

January 12, 2012
Tweet

More Decks by Nick Quaranto

Other Decks in Programming

Transcript

  1. Nick Quaranto
    @qrush [email protected]
    R B Y
    cutting your own RubyGems
    Wednesday, May 25, 2011

    View Slide

  2. P S A
    first, a
    Wednesday, May 25, 2011

    View Slide

  3. Where have all of
    the manuals gone?
    Wednesday, May 25, 2011

    View Slide

  4. http://history.nasa.gov/diagrams/gemini.html
    Wednesday, May 25, 2011

    View Slide

  5. http://history.nasa.gov/diagrams/gemini.html
    Wednesday, May 25, 2011

    View Slide

  6. http://archive.computerhistory.org/resources/text/Apple/Apple.AppleI.1976.102646518.pdf
    Wednesday, May 25, 2011

    View Slide

  7. http://archive.computerhistory.org/resources/text/Apple/Apple.AppleI.1976.102646518.pdf
    Wednesday, May 25, 2011

    View Slide

  8. http://archive.computerhistory.org/resources/text/Apple/Apple.AppleI.1976.102646518.pdf
    Wednesday, May 25, 2011

    View Slide

  9. http://archive.computerhistory.org/resources/text/Apple/Apple.AppleI.1976.102646518.pdf
    Wednesday, May 25, 2011

    View Slide

  10. http://ed-thelen.org/comp-hist/CRAY-1-HardRefMan/CRAY-1-HRM.html
    Wednesday, May 25, 2011

    View Slide

  11. http://ed-thelen.org/comp-hist/CRAY-1-HardRefMan/CRAY-1-HRM.html
    Wednesday, May 25, 2011

    View Slide

  12. http://ed-thelen.org/comp-hist/CRAY-1-HardRefMan/CRAY-1-HRM.html
    Wednesday, May 25, 2011

    View Slide

  13. http://guides.rubyonrails.org
    Wednesday, May 25, 2011

    View Slide

  14. http://progit.org
    Wednesday, May 25, 2011

    View Slide

  15. http://guides.sproutcore.org
    Wednesday, May 25, 2011

    View Slide

  16. We need
    MORE
    manuals!
    Wednesday, May 25, 2011

    View Slide

  17. MAKE
    MANUALS
    Wednesday, May 25, 2011

    View Slide

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

    View Slide

  19. G E M
    what is a gem?
    Wednesday, May 25, 2011

    View Slide

  20. Gems contain a
    packaged Ruby
    application or library.
    Wednesday, May 25, 2011

    View Slide

  21. RubyGems helps you
    download, install, and
    manipulate gems.
    Wednesday, May 25, 2011

    View Slide

  22. rubygems.org
    rubygems client
    Wednesday, May 25, 2011

    View Slide

  23. rubygems.org
    rubygems client
    gems
    Wednesday, May 25, 2011

    View Slide

  24. rubygems.org
    rubygems client
    gems,
    gemspecs,
    indexes
    from S3
    gems
    Wednesday, May 25, 2011

    View Slide

  25. .gem
    Wednesday, May 25, 2011

    View Slide

  26. Code Gemspec
    Docs
    Wednesday, May 25, 2011

    View Slide

  27. % tree freewill
    freewill/
    |-- bin/
    | `-- freewill
    |-- lib/
    | `-- freewill.rb
    |-- test/
    | `-- test_freewill.rb
    |-- README
    |-- Rakefile
    `-- freewill.gemspec
    Wednesday, May 25, 2011

    View Slide

  28. .gem Rails
    ???
    Wednesday, May 25, 2011

    View Slide

  29. Ruby looks on your
    $LOAD_PATH when
    you call Kernel#require
    Wednesday, May 25, 2011

    View Slide

  30. RubyGems manages
    your $LOAD_PATH
    Wednesday, May 25, 2011

    View Slide

  31. % 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

    View Slide

  32. % irb -rpp
    >> require 'rake'
    LoadError: no such file to load --
    rake
    from (irb):2:in `require'
    from (irb):2
    Wednesday, May 25, 2011

    View Slide

  33. >> 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

    View Slide

  34. RubyGems overrides
    Kernel#require
    RubyGems puts bin/ and
    lib/ on your $LOAD_PATH
    Wednesday, May 25, 2011

    View Slide

  35. Gemspec holds
    metadata & info
    about the gem
    Wednesday, May 25, 2011

    View Slide

  36. % 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 = '[email protected]'
    s.homepage = 'http://example.com'
    s.files = ["lib/freewill.rb"]
    end
    Wednesday, May 25, 2011

    View Slide

  37. A gem is just
    a tarball of
    tarballs
    Wednesday, May 25, 2011

    View Slide

  38. % 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

    View Slide

  39. A GEM IS A TARBALL
    WITHIN A TARBALL
    Wednesday, May 25, 2011

    View Slide

  40. WHY CAN’T I USE
    MY LINUX PACKAGE
    MANAGER THEN
    Wednesday, May 25, 2011

    View Slide

  41. Wednesday, May 25, 2011

    View Slide

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

    View Slide

  43. D Y I
    make your own gem
    Wednesday, May 25, 2011

    View Slide

  44. share/modularize code
    automate your process
    releasing a gem is easy!
    Wednesday, May 25, 2011

    View Slide

  45. first gem
    Wednesday, May 25, 2011

    View Slide

  46. Your gem
    needs a name
    Wednesday, May 25, 2011

    View Slide

  47. DO NOT CALL IT:
    [rR].*
    rials
    cheezburger
    kitty
    dicks
    Wednesday, May 25, 2011

    View Slide

  48. no capitals, please
    use underscores for spaces
    use dashes for extensions
    Wednesday, May 25, 2011

    View Slide

  49. % tree
    .
    ├── hola.gemspec
    └── lib
    └── hola.rb
    Wednesday, May 25, 2011

    View Slide

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

    View Slide

  51. require ‘hola’
    % tree
    .
    ├── hola.gemspec
    └── lib
    └── hola.rb
    Wednesday, May 25, 2011

    View Slide

  52. % 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 = '[email protected]'
    s.files = ["lib/hola.rb"]
    s.homepage =
    'http://rubygems.org/gems/hola'
    end
    Wednesday, May 25, 2011

    View Slide

  53. push
    install
    build
    Wednesday, May 25, 2011

    View Slide

  54. push
    install
    build
    LOCAL
    Wednesday, May 25, 2011

    View Slide

  55. push
    install
    build
    LOCAL
    REMOTE
    Wednesday, May 25, 2011

    View Slide

  56. % 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

    View Slide

  57. Wednesday, May 25, 2011

    View Slide

  58. Wednesday, May 25, 2011

    View Slide

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

    View Slide

  60. % irb -rubygems
    >> require 'hola'
    => true
    >> Hola.hi
    Hello world!
    Wednesday, May 25, 2011

    View Slide

  61. % irb -rubygems
    >> require 'hola'
    => true
    >> Hola.hi
    Hello world!
    require 'ubygems.rb'
    Wednesday, May 25, 2011

    View Slide

  62. Wednesday, May 25, 2011

    View Slide

  63. % 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: [email protected]
    Password:
    Signed in.
    Pushing gem to RubyGems.org...
    Successfully registered gem: hola (0.0.0)
    Wednesday, May 25, 2011

    View Slide

  64. push
    install
    build
    LOCAL
    REMOTE
    install list -r
    Wednesday, May 25, 2011

    View Slide

  65. % 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

    View Slide

  66. executable
    first gem
    Wednesday, May 25, 2011

    View Slide

  67. gems are like
    awesome shell aliases
    Wednesday, May 25, 2011

    View Slide

  68. % curl -s http://jsonip.com/ | \
    prettify_json.rb
    {
    "ip": "24.60.248.134"
    }
    Wednesday, May 25, 2011

    View Slide

  69. % mkdir bin
    % touch bin/hola
    % chmod a+x bin/hola
    Wednesday, May 25, 2011

    View Slide

  70. % cat bin/hola
    #!/usr/bin/env ruby
    require 'hola'
    puts Hola.hi(ARGV[0])
    Wednesday, May 25, 2011

    View Slide

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

    View Slide

  72. % 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')
    Wednesday, May 25, 2011

    View Slide

  73. % 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
    Wednesday, May 25, 2011

    View Slide

  74. % ruby -Ilib ./bin/hola
    Hello world!
    % ruby -Ilib ./bin/hola Baltimore
    Hello Baltimore!
    Wednesday, May 25, 2011

    View Slide

  75. % ruby -Ilib ./bin/hola
    Hello world!
    % ruby -Ilib ./bin/hola Baltimore
    Hello Baltimore!
    $LOAD_PATH.unshift(“lib”)
    Wednesday, May 25, 2011

    View Slide

  76. % hola
    Hello world!
    % hola Baltimore
    Hello Baltimore!
    Wednesday, May 25, 2011

    View Slide

  77. % head -4 hola.gemspec
    Gem::Specification.new do |s|
    s.name = 'hola'
    s.version = '0.0.1'
    s.executables << 'hola'
    Wednesday, May 25, 2011

    View Slide

  78. tests
    executable
    first gem
    Wednesday, May 25, 2011

    View Slide

  79. framework
    automation
    Wednesday, May 25, 2011

    View Slide

  80. framework
    automation
    rake
    thor
    Wednesday, May 25, 2011

    View Slide

  81. framework
    automation
    rake
    thor
    Test::Unit rspec
    bacon context
    matchy shoulda
    riot testy shindo
    zebra lemon dfect
    cucumber steak
    Wednesday, May 25, 2011

    View Slide

  82. Test your gem.
    Use whatever.
    Please test it.
    Wednesday, May 25, 2011

    View Slide

  83. http://test.rubygems.org
    Wednesday, May 25, 2011

    View Slide

  84. Wednesday, May 25, 2011

    View Slide

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

    View Slide

  86. % 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

    View Slide

  87. % 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

    View Slide

  88. tests
    executable
    first gem
    docs
    Wednesday, May 25, 2011

    View Slide

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

    View Slide

  90. At least have a README!
    Wednesday, May 25, 2011

    View Slide

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

    View Slide

  92. inline
    guides
    Wednesday, May 25, 2011

    View Slide

  93. inline
    guides
    nokogiri
    yard
    Wednesday, May 25, 2011

    View Slide

  94. inline
    guides
    nokogiri
    yard
    rails
    datamapper
    Wednesday, May 25, 2011

    View Slide

  95. # 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

    View Slide

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

    View Slide

  97. P T N
    patterns
    Wednesday, May 25, 2011

    View Slide

  98. more files
    Wednesday, May 25, 2011

    View Slide

  99. .
    └── lib
    ├── hola
    │ └── translator.rb
    └── hola.rb
    Wednesday, May 25, 2011

    View Slide

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

    View Slide

  101. .
    └── lib
    ├── hola
    │ └── translator.rb
    └── hola.rb
    WORSE:
    $LOAD_PATH.unshift "lib/hola"
    require "translator"
    Wednesday, May 25, 2011

    View Slide

  102. .
    └── lib
    ├── hola
    │ └── translator.rb
    └── hola.rb
    GOOD:
    require "hola/translator"
    Wednesday, May 25, 2011

    View Slide

  103. Keep only one
    top-level file in lib/
    Wednesday, May 25, 2011

    View Slide

  104. .
    └── lib
    ├── foo
    │ └── cgi.rb
    ├── foo.rb
    └── set.rb
    Wednesday, May 25, 2011

    View Slide

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

    View Slide

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

    View Slide

  107. semver
    more files
    Wednesday, May 25, 2011

    View Slide

  108. Have a sane
    versioning scheme
    Wednesday, May 25, 2011

    View Slide

  109. http://www.flickr.com/photos/ioerror/3014911710/lightbox/
    Wednesday, May 25, 2011

    View Slide

  110. 3
    3.1
    3.14
    3.141
    3.1415
    3.14159
    3.141592
    3.1415926
    Wednesday, May 25, 2011

    View Slide

  111. http://semver.org
    Wednesday, May 25, 2011

    View Slide

  112. 1.2.3
    MAJOR.MINOR.PATCH
    Wednesday, May 25, 2011

    View Slide

  113. 0.0.x
    implementation details
    small bug fixes
    PATCH
    Wednesday, May 25, 2011

    View Slide

  114. 0.x.0
    backwards compatible
    API changes
    MINOR
    Wednesday, May 25, 2011

    View Slide

  115. x.0.0
    backwards incompatible
    API changes
    MAJOR
    Wednesday, May 25, 2011

    View Slide

  116. dependencies
    semver
    more files
    Wednesday, May 25, 2011

    View Slide

  117. http://www.slideshare.net/copiousfreetime/gemology
    Wednesday, May 25, 2011

    View Slide

  118. Specify your
    dependencies
    Wednesday, May 25, 2011

    View Slide

  119. development
    runtime
    Wednesday, May 25, 2011

    View Slide

  120. development
    runtime
    what your
    gem
    needs to
    work
    Wednesday, May 25, 2011

    View Slide

  121. development
    runtime
    what your
    gem
    needs to
    work
    what your
    tests
    need to
    work
    Wednesday, May 25, 2011

    View Slide

  122. 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

    View Slide

  123. Avoid >=
    Wednesday, May 25, 2011

    View Slide

  124. 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

    View Slide

  125. 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
    It will always work!
    Wednesday, May 25, 2011

    View Slide

  126. 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

    View Slide

  127. 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

    View Slide

  128. releasing a gem
    is easy!
    Wednesday, May 25, 2011

    View Slide

  129. have a sane
    versioning scheme
    Wednesday, May 25, 2011

    View Slide

  130. MAKE
    MANUALS
    Wednesday, May 25, 2011

    View Slide

  131. T H X
    Thanks for listening!
    Big thanks to:
    thoughtbot
    Jeremy Hinegardner
    Nick Quaranto
    @qrush [email protected]
    http://guides.rubygems.org
    Wednesday, May 25, 2011

    View Slide