Pro Yearly is on sale from $80 to $50! »

Raising the Bar

Beadecf8bd4f93be801f2209dce663e6?s=47 tyerhunt
October 02, 2011

Raising the Bar

Now that there are now over 25,000 gems on RubyGems.org, it's time we took a step back to look at the quality of what we're producing and the best practices we can all follow that will benefit the community.

Other languages expend a lot of effort maintaining a standard coding style and consistent APIs among their shared libraries, but the Ruby community doesn't. This has done a lot to lower the barrier to entry and allow the Ruby ecosystem to flourish, but it has also produced a lot of code of questionable quality that doesn't always mesh well in our applications.

There are simple conventions we can follow, though, that will make a big difference in establishing a consistent baseline for our gems. These include things like writing gemspecs instead of Rake tasks that generate them, properly namespacing your libraries, and not polluting the load path. But there are also other practices that will benefit others, like producing good documentation, including binaries when needed, and establishing a sane versioning strategy.

We'll cover the full lifecycle of a gem from beginning to end, from your first push to RubyGems.org to making and accepting community contributions, and consider the conventions that we can establish each step of the way to increase the value of the gems we're producing.

Beadecf8bd4f93be801f2209dce663e6?s=128

tyerhunt

October 02, 2011
Tweet

Transcript

  1. Raising the Bar Writing Better Gems

  2. Tyler Hunt @tylerhunt

  3. None
  4. None
  5. None
  6. 28,973 GEMS

  7. ORMs Active Record DataMapper Sequel Og

  8. Web Frameworks Rack Rails Merb Sinatra Padrino Camping Ramaze Nitro

  9. Choice

  10. Benefits

  11. Detriments

  12. Solution?

  13. Creating a Gem Defining Conventions State of the Ecosystem

  14. Creating a Gem

  15. stardust.gem

  16. mkdir stardust cd stardust/

  17. vi stardust.gemspec

  18. Gem::Specification.new do |s| s.name = 'stardust' s.version = '0.0.1' s.summary

    = 'Video & Coffee' end
  19. gem build stardust.gemspec WARNING: no author specified WARNING: no description

    specified WARNING: no email specified WARNING: no homepage specified Successfully built RubyGem Name: stardust Version: 0.0.1 File: stardust-0.0.1.gem
  20. tar xvf stardust-0.0.1.gem x data.tar.gz x metadata.gz

  21. gunzip metadata.gz

  22. tar xzvf data.tar.gz

  23. lib/

  24. mkdir lib

  25. vi lib/stardust.rb

  26. module Stardust end

  27. Gem::Specification.new do |s| s.name = 'stardust' s.version = '0.0.1' s.summary

    = 'Video & Coffee' end
  28. Gem::Specification.new do |s| s.name = 'stardust' s.version = '0.0.1' s.summary

    = 'Video & Coffee' s.files = ['lib/stardust.rb'] s.require_paths = ['lib'] end
  29. mkdir lib/stardust

  30. Version

  31. vi lib/stardust/version.rb

  32. module Stardust VERSION = '0.0.1' end

  33. require 'stardust/version' module Stardust end

  34. Gem::Specification.new do |s| s.name = 'stardust' s.version = '0.0.1' s.summary

    = 'Video & Coffee' s.files = ['lib/stardust.rb'] s.require_paths = ['lib'] end
  35. $:.push File.expand_path('../lib', __FILE__) require 'stardust/version' Gem::Specification.new do |s| s.name =

    'stardust' s.version = '0.0.1' s.summary = 'Video & Coffee' s.files = ['lib/stardust.rb'] s.require_paths = ['lib'] end
  36. $:.push File.expand_path('../lib', __FILE__) require 'stardust/version' Gem::Specification.new do |s| s.name =

    'stardust' s.version = Stardust::VERSION s.summary = 'Video & Coffee' s.files = ['lib/stardust.rb'] s.require_paths = ['lib'] end
  37. Ship it!

  38. gem build stardust.gemspec

  39. gem push stardust-0.0.1.gem Pushing gem to RubyGems.org... Successfully registered gem:

    stardust (0.0.1)
  40. None
  41. Done.

  42. Dependencies

  43. Gem::Specification.new do |s| s.name = 'stardust' s.version = '0.0.1' s.summary

    = 'Video & Coffee' end
  44. Gem::Specification.new do |s| s.name = 'stardust' s.version = '0.0.1' s.summary

    = 'Video & Coffee' s.add_dependency 'activesupport', '~> 3.0.0' s.add_development_dependency 'rspec', '~> 2.3.0' end
  45. gem install stardust-0.0.1.gem Fetching: activesupport-3.0.10.gem (100%) Successfully installed activesupport-3.0.10 Successfully

    installed stardust-0.0.1 2 gems installed Installing ri documentation for activesupport-3.0.10... Installing ri documentation for stardust-0.0.1... Installing RDoc documentation for activesupport-3.0.10... Installing RDoc documentation for stardust-0.0.1...
  46. gem install \ stardust-0.0.1.gem \ --development

  47. Be Thoughtful

  48. A Gotcha

  49. Bundler

  50. vi Gemfile

  51. source 'http://rubygems.org' gemspec

  52. bundle

  53. bundle gem stardust

  54. git status # On branch master # # Initial commit

    # # Changes to be committed: # (use "git rm --cached <file>..." to unstage) # # new file: .gitignore # new file: Gemfile # new file: Rakefile # new file: lib/stardust.rb # new file: lib/stardust/version.rb # new file: stardust.gemspec
  55. Rake Tasks

  56. rake build

  57. rake install

  58. rake release

  59. Testing

  60. Write Tests!

  61. test/ spec/

  62. $:.unshift(File.expand_path('../../lib', __FILE__)) require 'rspec' require 'stardust'

  63. Read Tests!

  64. Defining Conventions

  65. lib/ bin/

  66. Namespacing

  67. $:

  68. __FILE__

  69. require 'rubygems'

  70. ruby -rubygems RUBYOPT=rubygems

  71. Class Variables

  72. Error Handling

  73. module Stardust Error = Class.new(StandardError) CustomError = Class.new(Error) end

  74. begin Stardust::Feature.new rescue Stardust::Error end

  75. Testing

  76. Documenting

  77. Packaging

  78. Releasing

  79. Versioning

  80. SemVer

  81. Public API

  82. X.Y.Z

  83. Immutable

  84. 0.y.z

  85. x.y.Z

  86. x.Y.z

  87. X.y.z

  88. vX.Y.Z

  89. ~> X.y

  90. http://semver.org/

  91. Community Contributions

  92. None
  93. Contribution Policy

  94. Bumping Versions

  95. State of the Ecosystem

  96. RubyGems.org

  97. 28,973 GEMS

  98. gem push

  99. quantity ≠ quality

  100. Gem or Custom?

  101. Duplicates?

  102. Rewrite?

  103. > quality

  104. < barriers

  105. Thanks

  106. None
  107. None
  108. None
  109. Thank You!

  110. Questions