Building A Gem From Scratch

Brian Hogan
Brian HoganProgrammer and writer.
Building A Gem From
                     Scratch
                                 Madison Ruby, 2011




twitter: bphogan
email: brianhogan at napcs.com
What's A Gem?



twitter: bphogan
email: brianhogan at napcs.com
The (normal) Process
           • Come up with an idea
           • write some code
           • Release a gem
           • Beg people to write tests for you

twitter: bphogan
email: brianhogan at napcs.com
Our process

           • Come up with an idea and write some code
           • Throw all that code away
           • Rewrite it with tests as we go
           • Release it as a Gem
           • Enjoy fame and fortune
twitter: bphogan
email: brianhogan at napcs.com
Grabatar
                        (a gem to grab Gravatar URLs)

                     http://www.gravatar.com/avatar/
                   6ef8cb7cd7cd58077f0b57e4fa49a969




twitter: bphogan
email: brianhogan at napcs.com
Step one: Build tested,
                 working code


twitter: bphogan
email: brianhogan at napcs.com
The basic structure of a
                   Gem
                                 gemname.gemspec
                                 lib/
                                        gemname
                                           version.rb
                                           anotherfile.rb
                                        gemname.rb

twitter: bphogan
email: brianhogan at napcs.com
Tests, Tests, Tests!




twitter: bphogan
email: brianhogan at napcs.com
Test::Unit
                                   test
                                          somefile_test.rb



twitter: bphogan
email: brianhogan at napcs.com
Write the test
   test/grabatar_test.rb

     require 'test/unit'
     require 'lib/grabatar'

     class GrabatarTest < Test::Unit::TestCase
       def test_displays_version
         assert Grabatar::VERSION
       end
     end




twitter: bphogan
email: brianhogan at napcs.com
Implement the code

   lib/grabatar/version.rb

      module Grabatar
        VERSION = "0.0.2"
      end




twitter: bphogan
email: brianhogan at napcs.com
Add to the main Ruby file:
   lib/grabatar.rb


     require 'grabatar/version'




twitter: bphogan
email: brianhogan at napcs.com
Repeat.



twitter: bphogan
email: brianhogan at napcs.com
Write the test first...
   test/gravatar_helper.rb

     require 'test/unit'
     require 'grabatar'

     class GravatarTest < Test::Unit::TestCase
       def test_builds_gravatar_url
         g = Grabatar::Gravatar.new("bphogan@gmail.com")
         assert_equal "http://www.gravatar.com/avatar/
                       6ef8cb7cd7cd58077f0b57e4fa49a969", g.avatar_url
       end
     end




twitter: bphogan
email: brianhogan at napcs.com
Then write the code
   lib/grabatar/gravatar.rb

      module Grabatar
        class Gravatar
          require 'digest/md5'

           def initialize(email)
             @email = email
           end

           def avatar_url
             hash = Digest::MD5.hexdigest(@email)
             "http://www.gravatar.com/avatar/#{hash}"
           end

        end
      end


twitter: bphogan
email: brianhogan at napcs.com
Then write the code
   lib/grabatar/gravatar.rb

      module Grabatar
        class Gravatar
          require 'digest/md5'

           def initialize(email)
             @email = email
           end

           def avatar_url
             hash = Digest::MD5.hexdigest(@email)
             "http://www.gravatar.com/avatar/#{hash}"
           end

        end
      end


twitter: bphogan
email: brianhogan at napcs.com
Then write the code
   lib/grabatar/gravatar.rb

      module Grabatar
        class Gravatar
          require 'digest/md5'

           def initialize(email)
             @email = email
           end

           def avatar_url
             hash = Digest::MD5.hexdigest(@email)
             "http://www.gravatar.com/avatar/#{hash}"
           end

        end
      end


twitter: bphogan
email: brianhogan at napcs.com
Then write the code
   lib/grabatar/gravatar.rb

      module Grabatar
        class Gravatar
          require 'digest/md5'

           def initialize(email)
             @email = email
           end

           def avatar_url
             hash = Digest::MD5.hexdigest(@email)
             "http://www.gravatar.com/avatar/#{hash}"
           end

        end
      end


twitter: bphogan
email: brianhogan at napcs.com
Step two: Make A
                         Gemspec


twitter: bphogan
email: brianhogan at napcs.com
Gemspecs are easy.
   grabatar.gemspec

     require 'lib/grabatar/version'
     Gem::Specification.new do |s|
       s.name = "grabatar"
       s.version = Grabatar::VERSION
       s.summary = "Fetch avatar image URLs from Gravatar"
       s.authors = ["Brian Hogan"]
       s.email = ["bphogan@gmail.com"]
       s.files = [
         "lib/grabatar.rb",
         "lib/grabatar/version.rb",
         "lib/grabatar/gravatar.rb",
         "lib/grabatar/railtie.rb",
         "lib/grabatar/view_helpers.rb"
       ]
     end


twitter: bphogan
email: brianhogan at napcs.com
Gemspecs are easy.
   grabatar.gemspec

     require 'lib/grabatar/version'
     Gem::Specification.new do |s|
       s.name = "grabatar"
       s.version = Grabatar::VERSION
       s.summary = "Fetch avatar image URLs from Gravatar"
       s.authors = ["Brian Hogan"]
       s.email = ["bphogan@gmail.com"]
       s.files = [
         "lib/grabatar.rb",
         "lib/grabatar/version.rb",
         "lib/grabatar/gravatar.rb",
         "lib/grabatar/railtie.rb",
         "lib/grabatar/view_helpers.rb"
       ]
     end


twitter: bphogan
email: brianhogan at napcs.com
Gemspecs are easy.
   grabatar.gemspec

     require 'lib/grabatar/version'
     Gem::Specification.new do |s|
       s.name = "grabatar"
       s.version = Grabatar::VERSION
       s.summary = "Fetch avatar image URLs from Gravatar"
       s.authors = ["Brian Hogan"]
       s.email = ["bphogan@gmail.com"]
       s.files = [
         "lib/grabatar.rb",
         "lib/grabatar/version.rb",
         "lib/grabatar/gravatar.rb",
         "lib/grabatar/railtie.rb",
         "lib/grabatar/view_helpers.rb"
       ]
     end


twitter: bphogan
email: brianhogan at napcs.com
Gemspecs are easy.
   grabatar.gemspec

     require 'lib/grabatar/version'
     Gem::Specification.new do |s|
       s.name = "grabatar"
       s.version = Grabatar::VERSION
       s.summary = "Fetch avatar image URLs from Gravatar"
       s.authors = ["Brian Hogan"]
       s.email = ["bphogan@gmail.com"]
       s.files = [
         "lib/grabatar.rb",
         "lib/grabatar/version.rb",
         "lib/grabatar/gravatar.rb",
         "lib/grabatar/railtie.rb",
         "lib/grabatar/view_helpers.rb"
       ]
     end


twitter: bphogan
email: brianhogan at napcs.com
The manifest




twitter: bphogan
email: brianhogan at napcs.com
bundle gem is bad for you
     s.files                = `git ls-files`.split("n")
     s.test_files           = `git ls-files --
                               {test,spec,features}/*`.split("n")
     s.executables          = `git ls-files -- bin/*`
                               .split("n").map{ |f| File.basename(f) }




twitter: bphogan
email: brianhogan at napcs.com
What lies beneath
           • .DS_Store
           • thumbs.db
           • ~whatever.rb
           • whatever.mine.rb
           • Step 3: Rake
           • Test::Unit tasks
twitter: bphogan
email: brianhogan at napcs.com
Craft your manifest by hand
    s.files = [
      "lib/grabatar.rb",
      "lib/grabatar/version.rb",
      "lib/grabatar/gravatar.rb",
      "lib/grabatar/railtie.rb",
      "lib/grabatar/view_helpers.rb"
    ]




twitter: bphogan
email: brianhogan at napcs.com
Build and install the gem
     $ gem build grabatar.gemspec
     $ gem install grabatar-0-0-1.gem




twitter: bphogan
email: brianhogan at napcs.com
Step 4: Rails gems



twitter: bphogan
email: brianhogan at napcs.com
Test first
   test/view_helpers_test.rb

     require 'test/unit'
     require 'grabatar/gravatar'
     require 'grabatar/view_helpers'

     class ViewHelpers < Test::Unit::TestCase
       include Grabatar::ViewHelpers
       def test_generates_avatar_url
         assert_equal
            "http://www.gravatar.com/avatar
             /6ef8cb7cd7cd58077f0b57e4fa49a969",
             gravatar_url_for("bphogan@gmail.com")
       end
     end




twitter: bphogan
email: brianhogan at napcs.com
Test first
   test/view_helpers_test.rb

     require 'test/unit'
     require 'grabatar/gravatar'
     require 'grabatar/view_helpers'

     class ViewHelpers < Test::Unit::TestCase
       include Grabatar::ViewHelpers
       def test_generates_avatar_url
         assert_equal
            "http://www.gravatar.com/avatar
             /6ef8cb7cd7cd58077f0b57e4fa49a969",
             gravatar_url_for("bphogan@gmail.com")
       end
     end




twitter: bphogan
email: brianhogan at napcs.com
Create a helper
   lib/grabatar/view_helpers.rb


      module Grabatar
        module ViewHelpers
          def gravatar_url_for(email)
            Grabatar::Gravatar.new(email).avatar_url
          end
        end
      end




twitter: bphogan
email: brianhogan at napcs.com
Railties



twitter: bphogan
email: brianhogan at napcs.com
Include the Helper
   lib/grabatar/railtie.rb


     module Grabatar
       class Railtie < Rails::Railtie
         initializer "grabatar.view_helpers" do
           ActionView::Base.send :include, ViewHelpers
         end
       end
     end




twitter: bphogan
email: brianhogan at napcs.com
Only load the Railtie if we have Rails
 lib/grabatar.rb


   require 'grabatar/railtie' if defined?(Rails)




twitter: bphogan
email: brianhogan at napcs.com
Making a CLI tool



twitter: bphogan
email: brianhogan at napcs.com
Add a bin folder with
                    the file!


twitter: bphogan
email: brianhogan at napcs.com
The CLI program
   bin/grabatar


     #!/usr/bin/env ruby
     require 'grabatar'

     puts "Grabatar v#{Grabatar::VERSION}"

     email = ARGV[0]

     if email.nil?
       puts "Usage: grabatar <youremail@server.com>"
     else
       g = Grabatar::Gravatar.new(email)
       puts g.avatar_url
     end




twitter: bphogan
email: brianhogan at napcs.com
The CLI program
   bin/grabatar


     #!/usr/bin/env ruby
     require 'grabatar'

     puts "Grabatar v#{Grabatar::VERSION}"

     email = ARGV[0]

     if email.nil?
       puts "Usage: grabatar <youremail@server.com>"
     else
       g = Grabatar::Gravatar.new(email)
       puts g.avatar_url
     end




twitter: bphogan
email: brianhogan at napcs.com
The CLI program
   bin/grabatar


     #!/usr/bin/env ruby
     require 'grabatar'

     puts "Grabatar v#{Grabatar::VERSION}"

     email = ARGV[0]

     if email.nil?
       puts "Usage: grabatar <youremail@server.com>"
     else
       g = Grabatar::Gravatar.new(email)
       puts g.avatar_url
     end




twitter: bphogan
email: brianhogan at napcs.com
Running it

     $ grabatar bphogan@gmail.com
     Grabatar v0.0.2
     http://www.gravatar.com/avatar/6ef8cb7cd7cd58077f0b57e4fa49a969




twitter: bphogan
email: brianhogan at napcs.com
Who wants code?
                     http://github.com/napcs/grabatar




twitter: bphogan
email: brianhogan at napcs.com
Thanks!
                                 http://spkr8.com/t/8181




twitter: bphogan
email: brianhogan at napcs.com
1 of 43

Recommended

Intro To Advanced Ruby by
Intro To Advanced RubyIntro To Advanced Ruby
Intro To Advanced RubyBrian Hogan
2.5K views48 slides
Stop Reinventing The Wheel - The Ruby Standard Library by
Stop Reinventing The Wheel - The Ruby Standard LibraryStop Reinventing The Wheel - The Ruby Standard Library
Stop Reinventing The Wheel - The Ruby Standard LibraryBrian Hogan
9.8K views95 slides
Plaxo OSCON 2006 by
Plaxo OSCON 2006Plaxo OSCON 2006
Plaxo OSCON 2006gueste8e0fb
527 views30 slides
Joseph-Smarr-Plaxo-OSCON-2006 by
Joseph-Smarr-Plaxo-OSCON-2006Joseph-Smarr-Plaxo-OSCON-2006
Joseph-Smarr-Plaxo-OSCON-2006guestfbf1e1
505 views30 slides
Web Scraper Shibuya.pm tech talk #8 by
Web Scraper Shibuya.pm tech talk #8Web Scraper Shibuya.pm tech talk #8
Web Scraper Shibuya.pm tech talk #8Tatsuhiko Miyagawa
17K views81 slides
From zero to almost rails in about a million slides... by
From zero to almost rails in about a million slides...From zero to almost rails in about a million slides...
From zero to almost rails in about a million slides...david_e_worth
583 views74 slides

More Related Content

What's hot

Create responsive websites with Django, REST and AngularJS by
Create responsive websites with Django, REST and AngularJSCreate responsive websites with Django, REST and AngularJS
Create responsive websites with Django, REST and AngularJSHannes Hapke
47.3K views50 slides
Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010 by
Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010
Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010singingfish
497 views53 slides
Beware the potholes on the road to serverless by
Beware the potholes on the road to serverlessBeware the potholes on the road to serverless
Beware the potholes on the road to serverlessYan Cui
690 views127 slides
High Performance Ajax Applications by
High Performance Ajax ApplicationsHigh Performance Ajax Applications
High Performance Ajax ApplicationsSiarhei Barysiuk
2.1K views77 slides
Looking Back to Move Forward: Building the Modern Web by
Looking Back to Move Forward: Building the Modern WebLooking Back to Move Forward: Building the Modern Web
Looking Back to Move Forward: Building the Modern WebRachel Andrew
41.4K views125 slides
HTML 5 & CSS 3 by
HTML 5 & CSS 3HTML 5 & CSS 3
HTML 5 & CSS 3Kevin van Dijk
3K views39 slides

What's hot(20)

Create responsive websites with Django, REST and AngularJS by Hannes Hapke
Create responsive websites with Django, REST and AngularJSCreate responsive websites with Django, REST and AngularJS
Create responsive websites with Django, REST and AngularJS
Hannes Hapke47.3K views
Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010 by singingfish
Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010
Don't RTFM, WTFM - Open Source Documentation - German Perl Workshop 2010
singingfish497 views
Beware the potholes on the road to serverless by Yan Cui
Beware the potholes on the road to serverlessBeware the potholes on the road to serverless
Beware the potholes on the road to serverless
Yan Cui690 views
High Performance Ajax Applications by Siarhei Barysiuk
High Performance Ajax ApplicationsHigh Performance Ajax Applications
High Performance Ajax Applications
Siarhei Barysiuk2.1K views
Looking Back to Move Forward: Building the Modern Web by Rachel Andrew
Looking Back to Move Forward: Building the Modern WebLooking Back to Move Forward: Building the Modern Web
Looking Back to Move Forward: Building the Modern Web
Rachel Andrew41.4K views
Opening up the Social Web - Standards that are bridging the Islands by Bastian Hofmann
Opening up the Social Web - Standards that are bridging the IslandsOpening up the Social Web - Standards that are bridging the Islands
Opening up the Social Web - Standards that are bridging the Islands
Bastian Hofmann9.3K views
Socket applications by João Moura
Socket applicationsSocket applications
Socket applications
João Moura601 views
HTTP/2 BrightonSEO 2018 by Tom Anthony
HTTP/2 BrightonSEO 2018HTTP/2 BrightonSEO 2018
HTTP/2 BrightonSEO 2018
Tom Anthony16K views
Big data beyond the JVM - DDTX 2018 by Holden Karau
Big data beyond the JVM -  DDTX 2018Big data beyond the JVM -  DDTX 2018
Big data beyond the JVM - DDTX 2018
Holden Karau155 views
Ajax to the Moon by davejohnson
Ajax to the MoonAjax to the Moon
Ajax to the Moon
davejohnson1.4K views
Web Development with Python and Django by Michael Pirnat
Web Development with Python and DjangoWeb Development with Python and Django
Web Development with Python and Django
Michael Pirnat188.7K views
DEF CON 27 - BEN SADEGHIPOUR - owning the clout through ssrf and pdf generators by Felipe Prado
DEF CON 27 - BEN SADEGHIPOUR  - owning the clout through ssrf and pdf generatorsDEF CON 27 - BEN SADEGHIPOUR  - owning the clout through ssrf and pdf generators
DEF CON 27 - BEN SADEGHIPOUR - owning the clout through ssrf and pdf generators
Felipe Prado140 views
Ruby Isn't Just About Rails by Adam Wiggins
Ruby Isn't Just About RailsRuby Isn't Just About Rails
Ruby Isn't Just About Rails
Adam Wiggins6.3K views
SearchLove San Diego 2018 | Tom Anthony | An Introduction to HTTP/2 & Service... by Distilled
SearchLove San Diego 2018 | Tom Anthony | An Introduction to HTTP/2 & Service...SearchLove San Diego 2018 | Tom Anthony | An Introduction to HTTP/2 & Service...
SearchLove San Diego 2018 | Tom Anthony | An Introduction to HTTP/2 & Service...
Distilled2.9K views
Building a desktop app with HTTP::Engine, SQLite and jQuery by Tatsuhiko Miyagawa
Building a desktop app with HTTP::Engine, SQLite and jQueryBuilding a desktop app with HTTP::Engine, SQLite and jQuery
Building a desktop app with HTTP::Engine, SQLite and jQuery
Tatsuhiko Miyagawa4.2K views
Twig: Friendly Curly Braces Invade Your Templates! by Ryan Weaver
Twig: Friendly Curly Braces Invade Your Templates!Twig: Friendly Curly Braces Invade Your Templates!
Twig: Friendly Curly Braces Invade Your Templates!
Ryan Weaver3K views

Similar to Building A Gem From Scratch

Intro to Ruby by
Intro to RubyIntro to Ruby
Intro to RubyBrian Hogan
1.7K views88 slides
Lightweight Webservices with Sinatra and RestClient by
Lightweight Webservices with Sinatra and RestClientLightweight Webservices with Sinatra and RestClient
Lightweight Webservices with Sinatra and RestClientAdam Wiggins
24.1K views47 slides
Merb Slices by
Merb SlicesMerb Slices
Merb Sliceshassox
2.5K views86 slides
Djabot – Python Jabber Bot by
Djabot – Python Jabber BotDjabot – Python Jabber Bot
Djabot – Python Jabber Botmarekkuziel
2.1K views18 slides
Freeing the cloud, one service at a time by
Freeing the cloud, one service at a timeFreeing the cloud, one service at a time
Freeing the cloud, one service at a timeFrancois Marier
720 views84 slides
Django로 만든 웹 애플리케이션 도커라이징하기 + 도커 컴포즈로 개발 환경 구축하기 by
Django로 만든 웹 애플리케이션 도커라이징하기 + 도커 컴포즈로 개발 환경 구축하기Django로 만든 웹 애플리케이션 도커라이징하기 + 도커 컴포즈로 개발 환경 구축하기
Django로 만든 웹 애플리케이션 도커라이징하기 + 도커 컴포즈로 개발 환경 구축하기raccoony
3.9K views123 slides

Similar to Building A Gem From Scratch(20)

Intro to Ruby by Brian Hogan
Intro to RubyIntro to Ruby
Intro to Ruby
Brian Hogan1.7K views
Lightweight Webservices with Sinatra and RestClient by Adam Wiggins
Lightweight Webservices with Sinatra and RestClientLightweight Webservices with Sinatra and RestClient
Lightweight Webservices with Sinatra and RestClient
Adam Wiggins24.1K views
Merb Slices by hassox
Merb SlicesMerb Slices
Merb Slices
hassox2.5K views
Djabot – Python Jabber Bot by marekkuziel
Djabot – Python Jabber BotDjabot – Python Jabber Bot
Djabot – Python Jabber Bot
marekkuziel2.1K views
Freeing the cloud, one service at a time by Francois Marier
Freeing the cloud, one service at a timeFreeing the cloud, one service at a time
Freeing the cloud, one service at a time
Francois Marier720 views
Django로 만든 웹 애플리케이션 도커라이징하기 + 도커 컴포즈로 개발 환경 구축하기 by raccoony
Django로 만든 웹 애플리케이션 도커라이징하기 + 도커 컴포즈로 개발 환경 구축하기Django로 만든 웹 애플리케이션 도커라이징하기 + 도커 컴포즈로 개발 환경 구축하기
Django로 만든 웹 애플리케이션 도커라이징하기 + 도커 컴포즈로 개발 환경 구축하기
raccoony 3.9K views
Monkeybars in the Manor by martinbtt
Monkeybars in the ManorMonkeybars in the Manor
Monkeybars in the Manor
martinbtt820 views
2018 the conf put git to work - increase the quality of your rails project... by Rodrigo Urubatan
2018 the conf   put git to work -  increase the quality of your rails project...2018 the conf   put git to work -  increase the quality of your rails project...
2018 the conf put git to work - increase the quality of your rails project...
Rodrigo Urubatan110 views
ChefConf 2012 Spiceweasel by Matt Ray
ChefConf 2012 SpiceweaselChefConf 2012 Spiceweasel
ChefConf 2012 Spiceweasel
Matt Ray1.2K views
Migrating Legacy Rails Apps to Rails 3 by Clinton Dreisbach
Migrating Legacy Rails Apps to Rails 3Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3
Clinton Dreisbach4.5K views
Toolbox of a Ruby Team by Arto Artnik
Toolbox of a Ruby TeamToolbox of a Ruby Team
Toolbox of a Ruby Team
Arto Artnik422 views
Writing Software not Code with Cucumber by Ben Mabey
Writing Software not Code with CucumberWriting Software not Code with Cucumber
Writing Software not Code with Cucumber
Ben Mabey83.2K views
Sinatra Rack And Middleware by Ben Schwarz
Sinatra Rack And MiddlewareSinatra Rack And Middleware
Sinatra Rack And Middleware
Ben Schwarz16.9K views
Agile Development With Hobo by Evarist Lobo
Agile Development With HoboAgile Development With Hobo
Agile Development With Hobo
Evarist Lobo589 views

More from Brian Hogan

Creating and Deploying Static Sites with Hugo by
Creating and Deploying Static Sites with HugoCreating and Deploying Static Sites with Hugo
Creating and Deploying Static Sites with HugoBrian Hogan
1.2K views65 slides
Automating the Cloud with Terraform, and Ansible by
Automating the Cloud with Terraform, and AnsibleAutomating the Cloud with Terraform, and Ansible
Automating the Cloud with Terraform, and AnsibleBrian Hogan
1.8K views80 slides
Create Development and Production Environments with Vagrant by
Create Development and Production Environments with VagrantCreate Development and Production Environments with Vagrant
Create Development and Production Environments with VagrantBrian Hogan
3.5K views43 slides
Docker by
DockerDocker
DockerBrian Hogan
1.2K views86 slides
Getting Started Contributing To Open Source by
Getting Started Contributing To Open SourceGetting Started Contributing To Open Source
Getting Started Contributing To Open SourceBrian Hogan
867 views34 slides
Rethink Frontend Development With Elm by
Rethink Frontend Development With ElmRethink Frontend Development With Elm
Rethink Frontend Development With ElmBrian Hogan
4.3K views64 slides

More from Brian Hogan(19)

Creating and Deploying Static Sites with Hugo by Brian Hogan
Creating and Deploying Static Sites with HugoCreating and Deploying Static Sites with Hugo
Creating and Deploying Static Sites with Hugo
Brian Hogan1.2K views
Automating the Cloud with Terraform, and Ansible by Brian Hogan
Automating the Cloud with Terraform, and AnsibleAutomating the Cloud with Terraform, and Ansible
Automating the Cloud with Terraform, and Ansible
Brian Hogan1.8K views
Create Development and Production Environments with Vagrant by Brian Hogan
Create Development and Production Environments with VagrantCreate Development and Production Environments with Vagrant
Create Development and Production Environments with Vagrant
Brian Hogan3.5K views
Getting Started Contributing To Open Source by Brian Hogan
Getting Started Contributing To Open SourceGetting Started Contributing To Open Source
Getting Started Contributing To Open Source
Brian Hogan867 views
Rethink Frontend Development With Elm by Brian Hogan
Rethink Frontend Development With ElmRethink Frontend Development With Elm
Rethink Frontend Development With Elm
Brian Hogan4.3K views
Testing Client-side Code with Jasmine and CoffeeScript by Brian Hogan
Testing Client-side Code with Jasmine and CoffeeScriptTesting Client-side Code with Jasmine and CoffeeScript
Testing Client-side Code with Jasmine and CoffeeScript
Brian Hogan4.9K views
FUD-Free Accessibility for Web Developers - Also, Cake. by Brian Hogan
FUD-Free Accessibility for Web Developers - Also, Cake.FUD-Free Accessibility for Web Developers - Also, Cake.
FUD-Free Accessibility for Web Developers - Also, Cake.
Brian Hogan3.2K views
Responsive Web Design by Brian Hogan
Responsive Web DesignResponsive Web Design
Responsive Web Design
Brian Hogan1.3K views
Web Development with CoffeeScript and Sass by Brian Hogan
Web Development with CoffeeScript and SassWeb Development with CoffeeScript and Sass
Web Development with CoffeeScript and Sass
Brian Hogan9.3K views
Turning Passion Into Words by Brian Hogan
Turning Passion Into WordsTurning Passion Into Words
Turning Passion Into Words
Brian Hogan1.1K views
HTML5 and CSS3 Today by Brian Hogan
HTML5 and CSS3 TodayHTML5 and CSS3 Today
HTML5 and CSS3 Today
Brian Hogan2.2K views
Web Development With Ruby - From Simple To Complex by Brian Hogan
Web Development With Ruby - From Simple To ComplexWeb Development With Ruby - From Simple To Complex
Web Development With Ruby - From Simple To Complex
Brian Hogan4.8K views
Intro to Ruby - Twin Cities Code Camp 7 by Brian Hogan
Intro to Ruby - Twin Cities Code Camp 7Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7
Brian Hogan2.2K views
Make GUI Apps with Shoes by Brian Hogan
Make GUI Apps with ShoesMake GUI Apps with Shoes
Make GUI Apps with Shoes
Brian Hogan10.4K views
Story-driven Testing by Brian Hogan
Story-driven TestingStory-driven Testing
Story-driven Testing
Brian Hogan1.2K views
Learning To Walk In Shoes by Brian Hogan
Learning To Walk In ShoesLearning To Walk In Shoes
Learning To Walk In Shoes
Brian Hogan1.4K views
Rails and Legacy Databases - RailsConf 2009 by Brian Hogan
Rails and Legacy Databases - RailsConf 2009Rails and Legacy Databases - RailsConf 2009
Rails and Legacy Databases - RailsConf 2009
Brian Hogan6.8K views

Recently uploaded

Data Integrity for Banking and Financial Services by
Data Integrity for Banking and Financial ServicesData Integrity for Banking and Financial Services
Data Integrity for Banking and Financial ServicesPrecisely
56 views26 slides
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ... by
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...ShapeBlue
83 views15 slides
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda... by
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...ShapeBlue
63 views13 slides
Why and How CloudStack at weSystems - Stephan Bienek - weSystems by
Why and How CloudStack at weSystems - Stephan Bienek - weSystemsWhy and How CloudStack at weSystems - Stephan Bienek - weSystems
Why and How CloudStack at weSystems - Stephan Bienek - weSystemsShapeBlue
111 views13 slides
Network Source of Truth and Infrastructure as Code revisited by
Network Source of Truth and Infrastructure as Code revisitedNetwork Source of Truth and Infrastructure as Code revisited
Network Source of Truth and Infrastructure as Code revisitedNetwork Automation Forum
42 views45 slides
20231123_Camunda Meetup Vienna.pdf by
20231123_Camunda Meetup Vienna.pdf20231123_Camunda Meetup Vienna.pdf
20231123_Camunda Meetup Vienna.pdfPhactum Softwareentwicklung GmbH
46 views73 slides

Recently uploaded(20)

Data Integrity for Banking and Financial Services by Precisely
Data Integrity for Banking and Financial ServicesData Integrity for Banking and Financial Services
Data Integrity for Banking and Financial Services
Precisely56 views
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ... by ShapeBlue
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...
Backroll, News and Demo - Pierre Charton, Matthias Dhellin, Ousmane Diarra - ...
ShapeBlue83 views
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda... by ShapeBlue
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...
Hypervisor Agnostic DRS in CloudStack - Brief overview & demo - Vishesh Jinda...
ShapeBlue63 views
Why and How CloudStack at weSystems - Stephan Bienek - weSystems by ShapeBlue
Why and How CloudStack at weSystems - Stephan Bienek - weSystemsWhy and How CloudStack at weSystems - Stephan Bienek - weSystems
Why and How CloudStack at weSystems - Stephan Bienek - weSystems
ShapeBlue111 views
Automating a World-Class Technology Conference; Behind the Scenes of CiscoLive by Network Automation Forum
Automating a World-Class Technology Conference; Behind the Scenes of CiscoLiveAutomating a World-Class Technology Conference; Behind the Scenes of CiscoLive
Automating a World-Class Technology Conference; Behind the Scenes of CiscoLive
What’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlue by ShapeBlue
What’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlueWhat’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlue
What’s New in CloudStack 4.19 - Abhishek Kumar - ShapeBlue
ShapeBlue131 views
PharoJS - Zürich Smalltalk Group Meetup November 2023 by Noury Bouraqadi
PharoJS - Zürich Smalltalk Group Meetup November 2023PharoJS - Zürich Smalltalk Group Meetup November 2023
PharoJS - Zürich Smalltalk Group Meetup November 2023
Noury Bouraqadi141 views
GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N... by James Anderson
GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N...GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N...
GDG Cloud Southlake 28 Brad Taylor and Shawn Augenstein Old Problems in the N...
James Anderson133 views
2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlue by ShapeBlue
2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlue2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlue
2FA and OAuth2 in CloudStack - Andrija Panić - ShapeBlue
ShapeBlue50 views
Transitioning from VMware vCloud to Apache CloudStack: A Path to Profitabilit... by ShapeBlue
Transitioning from VMware vCloud to Apache CloudStack: A Path to Profitabilit...Transitioning from VMware vCloud to Apache CloudStack: A Path to Profitabilit...
Transitioning from VMware vCloud to Apache CloudStack: A Path to Profitabilit...
ShapeBlue57 views
NTGapps NTG LowCode Platform by Mustafa Kuğu
NTGapps NTG LowCode Platform NTGapps NTG LowCode Platform
NTGapps NTG LowCode Platform
Mustafa Kuğu141 views
Igniting Next Level Productivity with AI-Infused Data Integration Workflows by Safe Software
Igniting Next Level Productivity with AI-Infused Data Integration Workflows Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Igniting Next Level Productivity with AI-Infused Data Integration Workflows
Safe Software344 views
TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f... by TrustArc
TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f...TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f...
TrustArc Webinar - Managing Online Tracking Technology Vendors_ A Checklist f...
TrustArc77 views
Developments to CloudStack’s SDN ecosystem: Integration with VMWare NSX 4 - P... by ShapeBlue
Developments to CloudStack’s SDN ecosystem: Integration with VMWare NSX 4 - P...Developments to CloudStack’s SDN ecosystem: Integration with VMWare NSX 4 - P...
Developments to CloudStack’s SDN ecosystem: Integration with VMWare NSX 4 - P...
ShapeBlue82 views
KVM Security Groups Under the Hood - Wido den Hollander - Your.Online by ShapeBlue
KVM Security Groups Under the Hood - Wido den Hollander - Your.OnlineKVM Security Groups Under the Hood - Wido den Hollander - Your.Online
KVM Security Groups Under the Hood - Wido den Hollander - Your.Online
ShapeBlue102 views
"Surviving highload with Node.js", Andrii Shumada by Fwdays
"Surviving highload with Node.js", Andrii Shumada "Surviving highload with Node.js", Andrii Shumada
"Surviving highload with Node.js", Andrii Shumada
Fwdays40 views

Building A Gem From Scratch

  • 1. Building A Gem From Scratch Madison Ruby, 2011 twitter: bphogan email: brianhogan at napcs.com
  • 2. What's A Gem? twitter: bphogan email: brianhogan at napcs.com
  • 3. The (normal) Process • Come up with an idea • write some code • Release a gem • Beg people to write tests for you twitter: bphogan email: brianhogan at napcs.com
  • 4. Our process • Come up with an idea and write some code • Throw all that code away • Rewrite it with tests as we go • Release it as a Gem • Enjoy fame and fortune twitter: bphogan email: brianhogan at napcs.com
  • 5. Grabatar (a gem to grab Gravatar URLs) http://www.gravatar.com/avatar/ 6ef8cb7cd7cd58077f0b57e4fa49a969 twitter: bphogan email: brianhogan at napcs.com
  • 6. Step one: Build tested, working code twitter: bphogan email: brianhogan at napcs.com
  • 7. The basic structure of a Gem gemname.gemspec lib/ gemname version.rb anotherfile.rb gemname.rb twitter: bphogan email: brianhogan at napcs.com
  • 8. Tests, Tests, Tests! twitter: bphogan email: brianhogan at napcs.com
  • 9. Test::Unit test somefile_test.rb twitter: bphogan email: brianhogan at napcs.com
  • 10. Write the test test/grabatar_test.rb require 'test/unit' require 'lib/grabatar' class GrabatarTest < Test::Unit::TestCase def test_displays_version assert Grabatar::VERSION end end twitter: bphogan email: brianhogan at napcs.com
  • 11. Implement the code lib/grabatar/version.rb module Grabatar VERSION = "0.0.2" end twitter: bphogan email: brianhogan at napcs.com
  • 12. Add to the main Ruby file: lib/grabatar.rb require 'grabatar/version' twitter: bphogan email: brianhogan at napcs.com
  • 14. Write the test first... test/gravatar_helper.rb require 'test/unit' require 'grabatar' class GravatarTest < Test::Unit::TestCase def test_builds_gravatar_url g = Grabatar::Gravatar.new("bphogan@gmail.com") assert_equal "http://www.gravatar.com/avatar/ 6ef8cb7cd7cd58077f0b57e4fa49a969", g.avatar_url end end twitter: bphogan email: brianhogan at napcs.com
  • 15. Then write the code lib/grabatar/gravatar.rb module Grabatar class Gravatar require 'digest/md5' def initialize(email) @email = email end def avatar_url hash = Digest::MD5.hexdigest(@email) "http://www.gravatar.com/avatar/#{hash}" end end end twitter: bphogan email: brianhogan at napcs.com
  • 16. Then write the code lib/grabatar/gravatar.rb module Grabatar class Gravatar require 'digest/md5' def initialize(email) @email = email end def avatar_url hash = Digest::MD5.hexdigest(@email) "http://www.gravatar.com/avatar/#{hash}" end end end twitter: bphogan email: brianhogan at napcs.com
  • 17. Then write the code lib/grabatar/gravatar.rb module Grabatar class Gravatar require 'digest/md5' def initialize(email) @email = email end def avatar_url hash = Digest::MD5.hexdigest(@email) "http://www.gravatar.com/avatar/#{hash}" end end end twitter: bphogan email: brianhogan at napcs.com
  • 18. Then write the code lib/grabatar/gravatar.rb module Grabatar class Gravatar require 'digest/md5' def initialize(email) @email = email end def avatar_url hash = Digest::MD5.hexdigest(@email) "http://www.gravatar.com/avatar/#{hash}" end end end twitter: bphogan email: brianhogan at napcs.com
  • 19. Step two: Make A Gemspec twitter: bphogan email: brianhogan at napcs.com
  • 20. Gemspecs are easy. grabatar.gemspec require 'lib/grabatar/version' Gem::Specification.new do |s| s.name = "grabatar" s.version = Grabatar::VERSION s.summary = "Fetch avatar image URLs from Gravatar" s.authors = ["Brian Hogan"] s.email = ["bphogan@gmail.com"] s.files = [ "lib/grabatar.rb", "lib/grabatar/version.rb", "lib/grabatar/gravatar.rb", "lib/grabatar/railtie.rb", "lib/grabatar/view_helpers.rb" ] end twitter: bphogan email: brianhogan at napcs.com
  • 21. Gemspecs are easy. grabatar.gemspec require 'lib/grabatar/version' Gem::Specification.new do |s| s.name = "grabatar" s.version = Grabatar::VERSION s.summary = "Fetch avatar image URLs from Gravatar" s.authors = ["Brian Hogan"] s.email = ["bphogan@gmail.com"] s.files = [ "lib/grabatar.rb", "lib/grabatar/version.rb", "lib/grabatar/gravatar.rb", "lib/grabatar/railtie.rb", "lib/grabatar/view_helpers.rb" ] end twitter: bphogan email: brianhogan at napcs.com
  • 22. Gemspecs are easy. grabatar.gemspec require 'lib/grabatar/version' Gem::Specification.new do |s| s.name = "grabatar" s.version = Grabatar::VERSION s.summary = "Fetch avatar image URLs from Gravatar" s.authors = ["Brian Hogan"] s.email = ["bphogan@gmail.com"] s.files = [ "lib/grabatar.rb", "lib/grabatar/version.rb", "lib/grabatar/gravatar.rb", "lib/grabatar/railtie.rb", "lib/grabatar/view_helpers.rb" ] end twitter: bphogan email: brianhogan at napcs.com
  • 23. Gemspecs are easy. grabatar.gemspec require 'lib/grabatar/version' Gem::Specification.new do |s| s.name = "grabatar" s.version = Grabatar::VERSION s.summary = "Fetch avatar image URLs from Gravatar" s.authors = ["Brian Hogan"] s.email = ["bphogan@gmail.com"] s.files = [ "lib/grabatar.rb", "lib/grabatar/version.rb", "lib/grabatar/gravatar.rb", "lib/grabatar/railtie.rb", "lib/grabatar/view_helpers.rb" ] end twitter: bphogan email: brianhogan at napcs.com
  • 24. The manifest twitter: bphogan email: brianhogan at napcs.com
  • 25. bundle gem is bad for you s.files = `git ls-files`.split("n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("n") s.executables = `git ls-files -- bin/*` .split("n").map{ |f| File.basename(f) } twitter: bphogan email: brianhogan at napcs.com
  • 26. What lies beneath • .DS_Store • thumbs.db • ~whatever.rb • whatever.mine.rb • Step 3: Rake • Test::Unit tasks twitter: bphogan email: brianhogan at napcs.com
  • 27. Craft your manifest by hand s.files = [ "lib/grabatar.rb", "lib/grabatar/version.rb", "lib/grabatar/gravatar.rb", "lib/grabatar/railtie.rb", "lib/grabatar/view_helpers.rb" ] twitter: bphogan email: brianhogan at napcs.com
  • 28. Build and install the gem $ gem build grabatar.gemspec $ gem install grabatar-0-0-1.gem twitter: bphogan email: brianhogan at napcs.com
  • 29. Step 4: Rails gems twitter: bphogan email: brianhogan at napcs.com
  • 30. Test first test/view_helpers_test.rb require 'test/unit' require 'grabatar/gravatar' require 'grabatar/view_helpers' class ViewHelpers < Test::Unit::TestCase include Grabatar::ViewHelpers def test_generates_avatar_url assert_equal "http://www.gravatar.com/avatar /6ef8cb7cd7cd58077f0b57e4fa49a969", gravatar_url_for("bphogan@gmail.com") end end twitter: bphogan email: brianhogan at napcs.com
  • 31. Test first test/view_helpers_test.rb require 'test/unit' require 'grabatar/gravatar' require 'grabatar/view_helpers' class ViewHelpers < Test::Unit::TestCase include Grabatar::ViewHelpers def test_generates_avatar_url assert_equal "http://www.gravatar.com/avatar /6ef8cb7cd7cd58077f0b57e4fa49a969", gravatar_url_for("bphogan@gmail.com") end end twitter: bphogan email: brianhogan at napcs.com
  • 32. Create a helper lib/grabatar/view_helpers.rb module Grabatar module ViewHelpers def gravatar_url_for(email) Grabatar::Gravatar.new(email).avatar_url end end end twitter: bphogan email: brianhogan at napcs.com
  • 34. Include the Helper lib/grabatar/railtie.rb module Grabatar class Railtie < Rails::Railtie initializer "grabatar.view_helpers" do ActionView::Base.send :include, ViewHelpers end end end twitter: bphogan email: brianhogan at napcs.com
  • 35. Only load the Railtie if we have Rails lib/grabatar.rb require 'grabatar/railtie' if defined?(Rails) twitter: bphogan email: brianhogan at napcs.com
  • 36. Making a CLI tool twitter: bphogan email: brianhogan at napcs.com
  • 37. Add a bin folder with the file! twitter: bphogan email: brianhogan at napcs.com
  • 38. The CLI program bin/grabatar #!/usr/bin/env ruby require 'grabatar' puts "Grabatar v#{Grabatar::VERSION}" email = ARGV[0] if email.nil? puts "Usage: grabatar <youremail@server.com>" else g = Grabatar::Gravatar.new(email) puts g.avatar_url end twitter: bphogan email: brianhogan at napcs.com
  • 39. The CLI program bin/grabatar #!/usr/bin/env ruby require 'grabatar' puts "Grabatar v#{Grabatar::VERSION}" email = ARGV[0] if email.nil? puts "Usage: grabatar <youremail@server.com>" else g = Grabatar::Gravatar.new(email) puts g.avatar_url end twitter: bphogan email: brianhogan at napcs.com
  • 40. The CLI program bin/grabatar #!/usr/bin/env ruby require 'grabatar' puts "Grabatar v#{Grabatar::VERSION}" email = ARGV[0] if email.nil? puts "Usage: grabatar <youremail@server.com>" else g = Grabatar::Gravatar.new(email) puts g.avatar_url end twitter: bphogan email: brianhogan at napcs.com
  • 41. Running it $ grabatar bphogan@gmail.com Grabatar v0.0.2 http://www.gravatar.com/avatar/6ef8cb7cd7cd58077f0b57e4fa49a969 twitter: bphogan email: brianhogan at napcs.com
  • 42. Who wants code? http://github.com/napcs/grabatar twitter: bphogan email: brianhogan at napcs.com
  • 43. Thanks! http://spkr8.com/t/8181 twitter: bphogan email: brianhogan at napcs.com

Editor's Notes

  1. \n
  2. Who here knows what a Gem is? Who&apos;s built a gem?\n
  3. \n
  4. \n
  5. Simple gem that fetches the Gravatar URL based on the given email\n
  6. This is the easy part.\n
  7. a lib folder, a &quot;main&quot; file that includes our other files\n
  8. Because they make for good code.\n
  9. Because it&apos;s there. I think Gems should try to have as few dependencies as possible.\n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. By hand. \n
  21. \n
  22. \n
  23. \n
  24. Lists all the files you wish to release with your Gem.\n
  25. It sure is handy, but its generated manifest is overkill. It depends on git. Maybe it&amp;#x2019;s not bad for you, but it sure makes me uncomfortable. It also requires that I use Git. I can remove these lines trivially. But it&amp;#x2019;s still uncomfortable.\n
  26. Things that automatically build manifests can (and do) accidentally include things like this, and more. And you can&apos;t put exceptions in for every possible type of IDE backup file or hidden folder a contributor might have.\n
  27. This way, you ensure that what&apos;s in the Gem is what you want, and what your contributors want. \n
  28. \n
  29. We can make our gems work with Rails. Let&apos;s make a really simple Rails helper\n
  30. Our helper will be a module, so we write a test that includes the module and tests that it returns the right result.\n
  31. Our helper will be a module, so we write a test that includes the module and tests that it returns the right result.\n
  32. \n
  33. We create a new class that inherits from Railtie and then mix our module into the view helpers\n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n