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

Building Your First Ruby Gem

Building Your First Ruby Gem

This slide deck was presented at the February meetup of Full Stack in Calrsbad, CA. Video of the presentation is available here: https://vimeo.com/60885543

Kevin Thompson

February 28, 2013
Tweet

Other Decks in Technology

Transcript

  1. A gem is an easily distributable package that contains a

    Ruby application or library. Thursday, February 28, 13
  2. What Are Ruby Gems Good For? ‣ Factoring reusable code

    out of an application Thursday, February 28, 13
  3. What Are Ruby Gems Good For? ‣ Factoring reusable code

    out of an application ‣ Simplifying complex functionality Thursday, February 28, 13
  4. What Are Ruby Gems Good For? ‣ Factoring reusable code

    out of an application ‣ Simplifying complex functionality ‣ Distributing command line executables Thursday, February 28, 13
  5. What Should A Ruby Gem Include? ‣ Code ‣ Gem

    Specification Thursday, February 28, 13
  6. What Should A Ruby Gem Include? ‣ Code ‣ Gem

    Specification ‣ Tests Thursday, February 28, 13
  7. What Should A Ruby Gem Include? ‣ Code ‣ Gem

    Specification ‣ Tests ‣ Documentation Thursday, February 28, 13
  8. hello !"" README.md !"" hello.gemspec #"" lib #"" hello.rb #""

    test #"" hello_test.rb <-------------------------------------- Documentation <---------------------------------- Gem Specification <----------------------------------- Code <------------------------------ Tests What Should A Ruby Gem Include? ‣ Code ‣ Gem Specification ‣ Tests ‣ Documentation Thursday, February 28, 13
  9. Name Your Gem ‣ Underscores for multi-word classes $ gem

    install hello_world ----------------------------> HelloWorld Thursday, February 28, 13
  10. Name Your Gem ‣ Underscores for multi-word classes $ gem

    install hello_world ----------------------------> HelloWorld $ gem install rails-hello_world ----------------------> Rails::HelloWorld ‣ Dashes for extensions Thursday, February 28, 13
  11. Name Your Gem ‣ Underscores for multi-word classes $ gem

    install hello_world ----------------------------> HelloWorld $ gem install rails-hello_world ----------------------> Rails::HelloWorld ‣ Dashes for extensions ‣ Make sure your name is available Thursday, February 28, 13
  12. Name Your Gem $ gem query --remote rails $ gem

    query --remote rails *** REMOTE GEMS *** aaronchi-jrails (0.5.1) aavkontakte-rails3 (0.1.7) abcjs-rails (1.5) ace-rails (0.0.2) ace-rails-ap (2.0.0) ... Thursday, February 28, 13
  13. $ gem query --remote --name-matches '^rails$' Name Your Gem $

    gem query --remote rails $ gem query --remote rails *** REMOTE GEMS *** aaronchi-jrails (0.5.1) aavkontakte-rails3 (0.1.7) abcjs-rails (1.5) ace-rails (0.0.2) ace-rails-ap (2.0.0) ... Thursday, February 28, 13
  14. $ gem query --remote --name-matches '^rails$' Name Your Gem $

    gem query --remote rails $ gem query --remote rails *** REMOTE GEMS *** aaronchi-jrails (0.5.1) aavkontakte-rails3 (0.1.7) abcjs-rails (1.5) ace-rails (0.0.2) ace-rails-ap (2.0.0) ... $ gem query --remote --name-matches '^rails$' *** REMOTE GEMS *** rails (3.2.12) Thursday, February 28, 13
  15. $ gem query --remote --name-matches '^rails$' Name Your Gem $

    gem query --remote rails $ gem query --remote rails *** REMOTE GEMS *** aaronchi-jrails (0.5.1) aavkontakte-rails3 (0.1.7) abcjs-rails (1.5) ace-rails (0.0.2) ace-rails-ap (2.0.0) ... $ gem query --remote --name-matches '^rails$' *** REMOTE GEMS *** rails (3.2.12) $ gem query -rn '^rails$' Thursday, February 28, 13
  16. Building Your Ruby Gem ‣ Name Your Gem ‣ Write

    Your Code Thursday, February 28, 13
  17. Write Your Code $ mkdir secret_agent $ cd secret_agent $

    touch secret_agent.gemspec $ touch README.md $ mkdir lib $ touch lib/secret_agent.rb $ mkdir test $ touch test/test_secret_agent.rb Thursday, February 28, 13
  18. Write Your Code $ mkdir secret_agent $ cd secret_agent $

    touch secret_agent.gemspec $ touch README.md $ mkdir lib $ touch lib/secret_agent.rb $ mkdir test $ touch test/test_secret_agent.rb secret_agent.gemspec Gem::Specification.new do |spec| spec.name = "secret_agent" spec.version = "0.0.1" spec.authors = ["Sterling Archer"] # ... Thursday, February 28, 13
  19. Write Your Code $ mkdir secret_agent $ cd secret_agent $

    touch secret_agent.gemspec $ touch README.md $ mkdir lib $ touch lib/secret_agent.rb $ mkdir test $ touch test/test_secret_agent.rb $ open http://google.com secret_agent.gemspec Gem::Specification.new do |spec| spec.name = "secret_agent" spec.version = "0.0.1" spec.authors = ["Sterling Archer"] # ... Thursday, February 28, 13
  20. Write Your Code $ gem install bundler $ bundle gem

    secret_agent Thursday, February 28, 13
  21. Write Your Code $ gem install bundler $ bundle gem

    secret_agent create secret_agent/Gemfile create secret_agent/Rakefile create secret_agent/LICENSE.txt create secret_agent/README.md create secret_agent/.gitignore create secret_agent/secret_agent.gemspec create secret_agent/lib/secret_agent.rb create secret_agent/lib/secret_agent/version.rb Thursday, February 28, 13
  22. Write Your Code $ gem install bundler $ bundle gem

    secret_agent create secret_agent/Gemfile create secret_agent/Rakefile create secret_agent/LICENSE.txt create secret_agent/README.md create secret_agent/.gitignore create secret_agent/secret_agent.gemspec create secret_agent/lib/secret_agent.rb create secret_agent/lib/secret_agent/version.rb require "bundler/gem_tasks" Rakefile Thursday, February 28, 13
  23. Write Your Code $ gem install bundler $ bundle gem

    secret_agent create secret_agent/Gemfile create secret_agent/Rakefile create secret_agent/LICENSE.txt create secret_agent/README.md create secret_agent/.gitignore create secret_agent/secret_agent.gemspec create secret_agent/lib/secret_agent.rb create secret_agent/lib/secret_agent/version.rb require "bundler/gem_tasks" Rakefile $ rake -T rake build # Build secret_agent-0.0.1.gem into the pkg directory. rake install # Build and install secret_agent-0.0.1.gem. rake release # Create tag v0.0.1 and build and push secret_agent-0.0.1. Thursday, February 28, 13
  24. Write Your Code source 'https://rubygems.org' # Specify your gem's dependencies

    in secret_agent.gemspec gemspec Gemfile Thursday, February 28, 13
  25. Write Your Code # coding: utf-8 lib = File.expand_path('../lib', __FILE__)

    $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'secret_agent/version' Gem::Specification.new do |spec| spec.name = "secret_agent" spec.version = SecretAgent::VERSION spec.authors = ["Sterling Archer"] spec.email = ["[email protected]"] # ... secret_agent.gemspec source 'https://rubygems.org' # Specify your gem's dependencies in secret_agent.gemspec gemspec Gemfile Thursday, February 28, 13
  26. Write Your Code # coding: utf-8 lib = File.expand_path('../lib', __FILE__)

    $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'secret_agent/version' Gem::Specification.new do |spec| spec.name = "secret_agent" spec.version = SecretAgent::VERSION spec.authors = ["Sterling Archer"] spec.email = ["[email protected]"] # ... secret_agent.gemspec source 'https://rubygems.org' # Specify your gem's dependencies in secret_agent.gemspec gemspec Gemfile Thursday, February 28, 13
  27. Write Your Code # ... spec.description = spec.summary = spec.homepage

    = spec.license = "MIT" spec.files = `git ls-files`.split($/) spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] spec.add_development_dependency "bundler", "~> 1.3" spec.add_development_dependency "rake" end secret_agent.gemspec %q{TODO: Write a gem description} %q{TODO: Write a gem summary} "" Thursday, February 28, 13
  28. Write Your Code # ... spec.description = spec.summary = spec.homepage

    = spec.license = "MIT" spec.files = `git ls-files`.split($/) spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] spec.add_development_dependency "bundler", "~> 1.3" spec.add_development_dependency "rake" end secret_agent.gemspec %q{Greet secret agents in style.} %q{Secret Agent Greetings} "http://dev.isis.org/secret_agent" Thursday, February 28, 13
  29. Write Your Code Copyright (c) 2013 Sterling Archer MIT License

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE ... LICENSE.txt Thursday, February 28, 13
  30. Write Your Code # ... spec.description = %q{Greet secret agents

    in style.} spec.summary = %q{Secret Agent Greetings} spec.homepage = "http://dev.isis.org/secret_agent" spec.license = "MIT" spec.files = `git ls-files`.split($/) spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] spec.add_development_dependency "bundler", "~> 1.3" spec.add_development_dependency "rake" end secret_agent.gemspec Thursday, February 28, 13
  31. Write Your Code *.gem *.rbc .bundle .config .yardoc Gemfile.lock InstalledFiles

    _yardoc coverage doc/ lib/bundler/man pkg rdoc spec/reports test/tmp test/version_tmp tmp .gitignore Thursday, February 28, 13
  32. Write Your Code # ... spec.description = %q{Greet secret agents

    in style.} spec.summary = %q{Secret Agent Greetings} spec.homepage = "http://dev.isis.org/secret_agent" spec.license = "MIT" spec.files = `git ls-files`.split($/) spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] spec.add_development_dependency "bundler", "~> 1.3" spec.add_development_dependency "rake" end secret_agent.gemspec Thursday, February 28, 13
  33. Building Your Ruby Gem ‣ Name Your Gem ‣ Write

    Your Code Thursday, February 28, 13
  34. Building Your Ruby Gem ‣ Name Your Gem ‣ Write

    Your Code Using TDD Thursday, February 28, 13
  35. Write Your Code Using TDD $ mkdir test $ touch

    test/test_secret_agent.rb Thursday, February 28, 13
  36. Write Your Code Using TDD $ mkdir test $ touch

    test/test_secret_agent.rb test/test_secret_agent.rb require 'test/unit' require 'secret_agent' class SecretAgentTest < Test::Unit::TestCase end Thursday, February 28, 13
  37. Write Your Code Using TDD $ mkdir test $ touch

    test/test_secret_agent.rb test/test_secret_agent.rb require 'test/unit' require 'secret_agent' class SecretAgentTest < Test::Unit::TestCase end def test_greet_without_name assert_equal "Greetings Agent", SecretAgent.greet end Thursday, February 28, 13
  38. Write Your Code Using TDD $ mkdir test $ touch

    test/test_secret_agent.rb test/test_secret_agent.rb require 'test/unit' require 'secret_agent' class SecretAgentTest < Test::Unit::TestCase end def test_greet_without_name assert_equal "Greetings Agent", SecretAgent.greet end def test_with_name assert_equal "Greetings Agent Archer", SecretAgent.greet('Archer') end Thursday, February 28, 13
  39. Write Your Code Using TDD $ ruby -I lib test/test_secret_agent.rb

    Run options: # Running tests: EE Finished tests in 0.000487s, 4106.7762 tests/s, 0.0000 assertions/s. 1) Error: test_with_name(SecretAgentTest): NoMethodError: undefined method `greet' for SecretAgent:Module test/test_secret_agent.rb:10:in `test_greet_with_name' 2) Error: test_without_name(SecretAgentTest): NoMethodError: undefined method `greet' for SecretAgent:Module test/test_secret_agent.rb:6:in `test_greet_without_name' 2 tests, 0 assertions, 0 failures, 2 errors, 0 skips Thursday, February 28, 13
  40. Write Your Code Using TDD require "secret_agent/version" module SecretAgent #

    Your code goes here... end lib/secret_agent.rb Thursday, February 28, 13
  41. Write Your Code Using TDD require "secret_agent/version" module SecretAgent #

    Your code goes here... end lib/secret_agent.rb require "secret_agent/version" module SecretAgent end Thursday, February 28, 13
  42. Write Your Code Using TDD require "secret_agent/version" module SecretAgent #

    Your code goes here... end lib/secret_agent.rb require "secret_agent/version" module SecretAgent end def self.greet(name = nil) "Greetings Agent #{name}".strip end Thursday, February 28, 13
  43. Write Your Code Using TDD require "secret_agent/version" module SecretAgent #

    Your code goes here... end lib/secret_agent.rb require "secret_agent/version" module SecretAgent end def self.greet(name = nil) "Greetings Agent #{name}".strip end $ ruby -I lib test/test_secret_agent.rb Run options: # Running tests: .. Finished tests in 0.000414s, 4830.9179 tests/s, 4830.9179 assertions/s. 2 tests, 2 assertions, 0 failures, 0 errors, 0 skips Thursday, February 28, 13
  44. Write Your Code Using TDD require "bundler/gem_tasks" require "rake/testtask" Rake::TestTask.new

    do |t| t.libs << "test" end desc "Run tests" task :default => :test Rakefile Thursday, February 28, 13
  45. Write Your Code Using TDD $ rake test require "bundler/gem_tasks"

    require "rake/testtask" Rake::TestTask.new do |t| t.libs << "test" end desc "Run tests" task :default => :test # Running tests: .. Finished tests in 0.000463s, 4319.6544 tests/s, 4319.6544 assertions/s. 2 tests, 2 assertions, 0 failures, 0 errors, 0 skips Rakefile Thursday, February 28, 13
  46. Write Your Code Using TDD $ mkdir bin $ touch

    bin/secret_agent $ chmod a+x bin/secret_agent Thursday, February 28, 13
  47. Write Your Code Using TDD $ mkdir bin $ touch

    bin/secret_agent $ chmod a+x bin/secret_agent #!/usr/bin/env ruby require 'secret_agent' puts SecretAgent.greet(ARGV[0]) bin/secret_agent Thursday, February 28, 13
  48. Write Your Code Using TDD $ mkdir bin $ touch

    bin/secret_agent $ chmod a+x bin/secret_agent #!/usr/bin/env ruby require 'secret_agent' puts SecretAgent.greet(ARGV[0]) bin/secret_agent $ ruby -I lib ./bin/secret_agent Greetings Agent $ ruby -I lib ./bin/secret_agent Figgis Greetings Agent Figgis Thursday, February 28, 13
  49. Building Your Ruby Gem ‣ Name Your Gem ‣ Write

    Your Code Using TDD Thursday, February 28, 13
  50. Building Your Ruby Gem ‣ Name Your Gem ‣ Write

    Your Code Using TDD ‣ Document Your Code Thursday, February 28, 13
  51. Document Your Code # SecretAgent ## Installation Add this line

    to your application's Gemfile: gem 'secret_agent' And then execute: $ bundle Or install it yourself as: $ gem install secret_agent ... README.md TODO: Write a gem description Thursday, February 28, 13
  52. Document Your Code # SecretAgent ## Installation Add this line

    to your application's Gemfile: gem 'secret_agent' And then execute: $ bundle Or install it yourself as: $ gem install secret_agent ... README.md Greet secret agents in style. Thursday, February 28, 13
  53. Document Your Code ... ## Usage TODO: Write usage instructions

    here ## Contributing 1. Fork it 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request README.md Thursday, February 28, 13
  54. Document Your Code ... ## Usage README.md ## Contributing 1.

    Fork it ... Thursday, February 28, 13
  55. Document Your Code ... ## Usage README.md ## Contributing 1.

    Fork it ... Once you've installed the gem, you can include the gem in your application: require 'secret_agent' puts SecretAgent.greet('Archer') #=> Greetings Agent Archer You can also use the gem as a command line utility: $ secret_agent Figgis Greetings Agent Figgis Thursday, February 28, 13
  56. Building Your Ruby Gem ‣ Name Your Gem ‣ Write

    Your Code Using TDD ‣ Document Your Code Thursday, February 28, 13
  57. Building Your Ruby Gem ‣ Name Your Gem ‣ Write

    Your Code Using TDD ‣ Document Your Code ‣ Publish Your Gem Thursday, February 28, 13
  58. Publish Your Gem $ git add --all $ git commit

    -m 'Initial commit.' Thursday, February 28, 13
  59. Publish Your Gem $ git add --all $ git commit

    -m 'Initial commit.' secret_agent 0.0.1 built to pkg/secret_agent-0.0.1.gem. secret_agent (0.0.1) installed. $ rake install Thursday, February 28, 13
  60. Publish Your Gem $ git add --all $ git commit

    -m 'Initial commit.' secret_agent 0.0.1 built to pkg/secret_agent-0.0.1.gem. secret_agent (0.0.1) installed. $ secret_agent Greetings Agent $ secret_agent Kane Greetings Agent Kane $ rake install Thursday, February 28, 13
  61. Publish Your Gem $ open http://rubygems.org/users/new $ curl -u your_username

    \ https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials Thursday, February 28, 13
  62. Publish Your Gem $ git remote add origin [email protected]:isis/secret_agent.git $

    git push --set-upstream origin master Thursday, February 28, 13
  63. Publish Your Gem $ git remote add origin [email protected]:isis/secret_agent.git $

    git push --set-upstream origin master $ rake release secret_agent 0.0.1 built to pkg/secret_agent-0.0.1.gem. Tagged v0.0.1. Pushed git commits and tags. Pushed secret_agent 0.0.1 to rubygems.org. Thursday, February 28, 13
  64. Publish Your Gem $ gem push pkg/secret_agent-0.0.1.gem Pushing gem to

    https://rubygems.org... Successfully registered gem: secret_agent (0.0.1) Thursday, February 28, 13
  65. Publish Your Gem $ gem query -rn '^secret_agent$' *** REMOTE

    GEMS *** secret_agent (0.0.1) Thursday, February 28, 13
  66. Publish Your Gem $ gem query -rn '^secret_agent$' *** REMOTE

    GEMS *** secret_agent (0.0.1) $ gem install secret_agent Successfully installed secret_agent-0.0.1 1 gem installed Thursday, February 28, 13
  67. $ secret_agent Publish Your Gem $ gem query -rn '^secret_agent$'

    *** REMOTE GEMS *** secret_agent (0.0.1) $ gem install secret_agent Successfully installed secret_agent-0.0.1 1 gem installed Greetings Agent $ secret_agent Gillette Greetings Agent Gillette Thursday, February 28, 13
  68. Building Your Ruby Gem ‣ Name Your Gem ‣ Write

    Your Code Using TDD ‣ Document Your Code ‣ Publish Your Gem Thursday, February 28, 13