Slide 1

Slide 1 text

Cut and Polish A Guide to Crafting Gems Good afternoon everyone - I hope you’re all ready to learn about how to write gems!

Slide 2

Slide 2 text

Pat Allan @pat freelancing-gods.com My name’s Pat, yes, I’m from Australia as well - hopefully you can understand me through my accent. Here’s my twitter handle and blog, if you’re interested.

Slide 3

Slide 3 text

“Use rubygems to publish your gem to rubygems” Now really, it’s pretty simple... you just use rubygems to publish your gem to rubygems. Oh wait, that’s almost recursive... let me try again.

Slide 4

Slide 4 text

“Use rubygems to publish your gem to rubygems” Now really, it’s pretty simple... you just use rubygems to publish your gem to rubygems. Oh wait, that’s almost recursive... let me try again.

Slide 5

Slide 5 text

“Use gem to publish your gem to rubygems” You use gem to publish your gem to rubygems. Wait, no, that isn’t quite clear either...

Slide 6

Slide 6 text

“Use gem to publish your gem to rubygems” You use gem to publish your gem to rubygems. Wait, no, that isn’t quite clear either...

Slide 7

Slide 7 text

“Use the gem command to publish your gem to rubygems.org” You use the gem command to publish your gem to rubygems.org. Okay, that’s a bit better, but it’s still not ideal... this isn’t looking quite so simple any more, is it. Let’s try to clarify things.

Slide 8

Slide 8 text

noun a precious or semiprecious stone, esp. when cut and polished or engraved. |jem| gem First, what’s a gem? Well, this is the definition anyone who isn’t a developer would expect...

Slide 9

Slide 9 text

noun a packaged code library written in the Ruby programming language. |jem| gem But we’re talking about bytes and electrons - so for us, a gem is library of Ruby code.

Slide 10

Slide 10 text

noun a command line executable distributed with the RubyGems package manager. |jem| gem Of course, it’s *also* a command line tool installed as part of rubygems. And what’s rubygems?

Slide 11

Slide 11 text

noun a package manager for Ruby libraries. |ˈro͞obējemz| rubygems Well, it’s essentially a package manager for gems.

Slide 12

Slide 12 text

noun a website that stores published versions of Ruby gems. |ˈro͞obējemz| rubygems But it’s also the site that hosts all published versions of gems. If you get confused between these definitions during this talk, please let me know. I’ll try to be as clear as possible.

Slide 13

Slide 13 text

Why? But first - why should we even care about creating gems?

Slide 14

Slide 14 text

Why? re-use code Well, they let us re-use our own code easily between projects - and you can let others use them as well.

Slide 15

Slide 15 text

Why? easy to install They’re also pretty easy to install - at least, in most cases.

Slide 16

Slide 16 text

Why? easy to share And thanks to rubygems, they’re really easy to share! And shared code is happy code.

Slide 17

Slide 17 text

History When did this all begin? Let’s run through a quick history lesson.

Slide 18

Slide 18 text

History 2003 rubyforge.org rubyforge began in 2003 - before there was the concept of gems.

Slide 19

Slide 19 text

History 2004 rubygems But that soon followed, the following year, with the release of the rubygems package manager for distributing gems.

Slide 20

Slide 20 text

“If you have libraries you would like to include, please send the gem les to either myself or Rich Kilmer” Chad Fowler, 15 March 2004 Back then, though, the way to get a gem published was to email Chad or Rich - not ideal.

Slide 21

Slide 21 text

History gems were magical And there was still some mystery about constructing gems.

Slide 22

Slide 22 text

History permission was required Even when they moved beyond email to something a little more automated, you still needed permission to publish a new gem - though they weren’t too fussy about allowing people to do this.

Slide 23

Slide 23 text

History 2009 gemcutter.org But two years ago, gemcutter hit the scene - initially as an alternative gem source.

Slide 24

Slide 24 text

History anyone can publish It made publishing gems easy - a simple shell command - and anyone was allowed to publish gems.

Slide 25

Slide 25 text

History rubygems.org And so it was adopted as the default gem source, and migrated to rubygems.org. And Rubyists rejoiced!

Slide 26

Slide 26 text

Gemspecs That’s all well and good, but I’m supposed to be telling you about how to write gems - and every gem revolves around a gemspec.

Slide 27

Slide 27 text

Gemspecs kyiv.gemspec Every gem has a gemspec - with the gem’s name. This file holds all the settings for your gem, and has a list of every file and dependency.

Slide 28

Slide 28 text

# kyiv.gemspec Gem::Specification.new do |s| s.name = ‘kyiv’ s.version = ‘0.0.1’ s.authors = [‘Pat Allan’] s.email = [‘[email protected]’] s.homepage = ‘’ s.summary = ‘RubyC Kyiv Gem’ s.description = ‘’ s.files = [...] s.test_files = [...] s.executables = [...] end Here’s an example gemspec. There’s nothing too scary here, it’s standard Ruby, and we’re just going through setting some options.

Slide 29

Slide 29 text

s.name = ‘kyiv’ Naming At the top we’ve got the name. You can call your gem whatever you like, but it must be unique. If someone else has already released a gem of the same name, bad luck, find something else to call yours.

Slide 30

Slide 30 text

Naming # name ‘will_paginate’ # requiring require ‘will_paginate’ # Class/Module WillPaginate Also: keep it lowercase, and as a general rule, use underscores for word separation...

Slide 31

Slide 31 text

Naming # name ‘cucumber-rails’ # requiring require ‘cucumber/rails’ # Class/Module Cucumber::Rails ... and hyphens for namespacing. These are not rules, just recommendations - I’ve failed to follow them in the past, as have many others.

Slide 32

Slide 32 text

Versions s.version = ‘0.0.1’ Next is the version number of your gem.

Slide 33

Slide 33 text

Versions s.version = ‘Major.Minor.Release’ You can choose any numbering system you like, but the vast majority of gems follow the standard Major/Minor/Release system.

Slide 34

Slide 34 text

Versions Major Versions Major version numbers indicate major changes - if your gem changes its external behaviour or main class and method structure. If people upgrade, are they going to have to change their code that’s using your code? If the answer is definitely yes, that would warrant bumping up the major version number.

Slide 35

Slide 35 text

Versions Minor Versions Minor version numbers are useful to indicate new features and minor changes to behaviour - things which are useful, but won’t require changes for existing usage.

Slide 36

Slide 36 text

Versions Release Versions And finally the release number - you want to change this for bug fixes and very small changes.

Slide 37

Slide 37 text

Versions Reference I would recommend separating the gem version out into a separate ruby file, so developers can check which version of your gem - within their code - they are using.

Slide 38

Slide 38 text

Versions # lib/kyiv/version.rb module Kyiv VERSION = ‘0.0.1’ end Such a file would look something like this - with a constant containing our version number.

Slide 39

Slide 39 text

Versions # kyiv.gemspec require ‘kyiv/version’ # ... s.version = Kyiv::VERSION And then the gemspec would look like this. Note that we’re only requiring the version file, not the entire library - we don’t want to load our entire gem just to determine the version number and generate our gemspec.

Slide 40

Slide 40 text

Versions VERSION = ‘1.0.0.beta1’ Here’s an example of releasing a beta version of a gem - if your gem version has any alphabetical characters, then it’s considered a pre-release - whether that’s a beta, release candidate or something else. This means it won’t be installed by default, only when explicitly requested.

Slide 41

Slide 41 text

Authors, Emails & Homepage s.authors = [‘Pat Allan’] s.email = [‘[email protected]’] s.homepage = ‘http:// github.com/pat/kyiv’ These settings are pretty self-explanatory - the gem authors’ names and email addresses. Both of these settings accept arrays, so you can list all of the authors. And you can also provide the home page for the gem - at the very least, put the Github repository here.

Slide 42

Slide 42 text

Summary & Description s.summary = ‘RubyC Kyiv Gem’ s.description = ‘Extended detail’ The gemspec expects both a summary and description - and it complains if they’re the same. The summary should be a very short description of your gem - and the description should be much more detailed.

Slide 43

Slide 43 text

Files s.files = [ ‘lib/kyiv.rb’, ‘lib/kyiv/version.rb’, ‘README.textile’, ‘LICENCE’ ] Now we get to the core of a gem - a listing of the relevant files. You want to have all files listed here that are required for the gem to work and be used - so, all ruby files, but also the README, LICENCE, and a HISTORY file if you have one too.

Slide 44

Slide 44 text

Files lib/kyiv.rb All files that can be required should exist under the lib directory. You can put them elsewhere, but I’ve never seen a good reason to do that. So just put them in lib. And you want a file there that matches the name of your gem.

Slide 45

Slide 45 text

Files Kyiv::Tourist lib/kyiv/tourist.rb Kyiv::Translator lib/kyiv/translator.rb All other relevant files should be placed within a gem’s project directory in lib, and namespaced accordingly - you want to avoid conflicts with any other gems.

Slide 46

Slide 46 text

Files # Don’t do this lib/kyiv.rb lib/tourist.rb lib/translator.rb You don’t want to do anything like this - because what happens if there’s also a gem named ‘tourist’?

Slide 47

Slide 47 text

Information Files README Always have a README file in your gem, with some information on how to install and use the gem. You can write it as a plain text file, or Textile or Markdown or RDoc - that’s up to you - but just make sure it’s there and helpful.

Slide 48

Slide 48 text

Information Files LICENCE Don’t forget to have a file with your open source licence of choice, too. You’ll find most gems are released under MIT or BSD licences - very few opt for the GPL, which can make it harder for developers to use your gem.

Slide 49

Slide 49 text

Information Files HISTORY This - or a change log - is optional, but recommended. It’s a great way for you and those who use your gem to see what’s changed in each release - and once your gem has been around a while, having that information becomes even more helpful.

Slide 50

Slide 50 text

Test Files s.test_files = [ ‘spec/kyiv_spec.rb’, ‘spec/spec_helper.rb’ ] And of course you’re writing tests for your gem, right? You can list your test files in your gemspec as well - again, best to follow standard practices here and put them in test or spec directories.

Slide 51

Slide 51 text

Test Files Beware Large Test Suites Now, if your gem’s test suite gets rather large - perhaps you’ve got a stack of fixture files - then it’s better not to include those files in your gem at all - otherwise you’re going to increase the gem size dramatically. That said, this is rare, so in most cases, include your tests.

Slide 52

Slide 52 text

Test Files Travis CI I highly recommend using Travis CI for continuous integration - it allows you to easily test across different versions of Ruby, including JRuby and Rubinius.

Slide 53

Slide 53 text

Executables s.executables = [ ‘bin/kyiv’ ] Not all gems will have executables, but some will - and you need to list them in your gemspec accordingly. They should live in the bin directory, and have executable permissions - and no file extension.

Slide 54

Slide 54 text

Executables #!/usr/bin/env ruby require ‘kyiv’ Kyiv::CLI.run Here’s an example of what could go in an executable file - you’ve got your shebang at the top, and then the ruby code that handles the command line interface. I highly recommend keeping this file very small and putting all the logic in a class in your lib directory. This makes your gem code much easier to test, maintain and re-use.

Slide 55

Slide 55 text

# kyiv.gemspec Gem::Specification.new do |s| s.name = ‘kyiv’ s.version = ‘0.0.1’ s.authors = [‘Pat Allan’] s.email = [‘[email protected]’] s.homepage = ‘’ s.summary = ‘RubyC Kyiv Gem’ s.description = ‘’ s.files = [...] s.test_files = [...] s.executables = [...] end So, going back to our gemspec, that’s our core settings all covered. There are others though - and the most important of these are our dependencies on other gems.

Slide 56

Slide 56 text

Dependencies s.add_runtime_dependency ‘rails’, ‘>= 3.0.0’ Gemspecs have a distinction between runtime dependencies - things your gem needs when it is running and being used by others - and development dependencies, which are required to develop the gem. So, your gem may need Rails to work - so you’d add a line like this to your gemspec.

Slide 57

Slide 57 text

Dependencies s.add_development_dependency ‘rspec’, ‘>= 2.6.0’ And given I’m using RSpec to test my gem, then I want to have it as a dependency as well - but only a development dependency. It doesn’t need to be installed for users of my gem.

Slide 58

Slide 58 text

Dependencies Dependency Versions It can be a little tricky to determine which version you want your dependencies to require - you don’t want it too restrictive, but you also don’t want it to break in the future.

Slide 59

Slide 59 text

Dependencies s.add_runtime_dependency ‘rails’, ‘~> 3.1’ This ensures any release of Rails that is equal to or greater than 3.1 can be used, but not Rails 4 - and going by our major/minor/release version number approach, this should hopefully be safe enough, because Rails shouldn’t go making any dramatic changes until 4.0. Of course, that’s not always true, but you can’t account for everything!

Slide 60

Slide 60 text

Dependencies ~> I’m guessing most of you have seen this version constraint before - but does everyone understand what it means? I know this is a slight tangent, but just quickly - it’s known as the pessimistic version constraint.

Slide 61

Slide 61 text

Dependencies ~> 3.1 == [>= 3.1 && < 4.0] ~> 3.0.3 == [>= 3.0.3 && < 3.1] You can see here that how specific you are is taken into account - it allows for an increase in the last digit specified, but not any before that. Anyway, you can read more about that online - back to dependencies!

Slide 62

Slide 62 text

Dependencies s.add_development_dependency ‘rspec’, ‘= 2.6.0’ It doesn’t hurt to be a bit more exact with your development dependencies - as this will allow other contributors to easily get a local copy set up.

Slide 63

Slide 63 text

Rake Tasks To assist development of your gem, you’re probably going to have a Rakefile in the root of your project with some tasks defined.

Slide 64

Slide 64 text

# run tests rake spec # generate documentation rake yard # default task should run tests rake These tasks may be for running tests and generating documentation - and perhaps helping with managing releases of the gem as well. It’s generally expected that the default task - which runs when you invoke rake with no argument - should run your entire test suite.

Slide 65

Slide 65 text

Publishing So, you’ve got the first version of your gem ready to go, the tests are all green, and now it’s time to share it with the world! How do you do that?

Slide 66

Slide 66 text

Publishing gem build kyiv.gemspec #=> kyiv-0.0.1.gem First things first: let’s generate the actual gem file - which is done by passing our gemspec into the ‘gem build’ command. This packages our gem together - into a file that includes the current version number.

Slide 67

Slide 67 text

Gem Files .gem == .tar If you’re curious, a gem file is just a tar file - and inside that is a compressed copy of your code, and the metadata from the gemspec.

Slide 68

Slide 68 text

Publishing gem push kyiv-0.0.1.gem Getting that gem file up onto rubygems.org is a single command - ‘gem push’. You’ll need to have signed up for an account on rubygems.org, and it’ll prompt you for your details once, and then remember them. But it really is just a matter of typing out that command, and that’ll upload the file!

Slide 69

Slide 69 text

Publishing Permanent It’ll take a few seconds for that gem version to be available to everyone - but once it’s up there, that’s it. You can’t change an existing version of a gem - if you made a mistake, bad luck, fix things and release a new version.

Slide 70

Slide 70 text

Publishing (Don’t) Yank However, if you’ve really screwed up - perhaps released some code that deletes files off of someone’s machine, or has an extremely serious security flaw - then you may want to yank it - which just means no one will be able to install that version of the gem any more. Yanking gems is only for emergencies - it’s unlikely you should ever need to do it.

Slide 71

Slide 71 text

Publishing MRI 1.9 Caution For the most part, developing and deploying on Ruby 1.9 is a smooth experience - and I recommend it - but there can be issues with building gems, because of the different way YAML is parsed. So it’s best to use MRI 1.8 when building the gem at the moment - hopefully soon this won’t be the case.

Slide 72

Slide 72 text

Community And once your gem is out there available for everyone to use, you may want to consider a few things...

Slide 73

Slide 73 text

Community Support Firstly, if you do want others to use your gem, then you’re probably going to need to offer some support - whether that’s via GitHub issues, or a mailing list, or some other way.

Slide 74

Slide 74 text

Community GitHub Speaking of GitHub, keep an eye out for pull requests - and encourage others to contribute. Perhaps have some guidelines on this in your README. Don’t be afraid to curate the patches, as well - accept ones you like, and provide feedback on ones you don’t want to merge in immediately. Be honest but friendly.

Slide 75

Slide 75 text

Community Releases And as your gem evolves, you can release new versions. It’s up to you on how often this happens - but try not to go overboard, and try not to break things.

Slide 76

Slide 76 text

Bundler Now, you may want to use Bundler locally to outline the gems you’re using to develop your gem.

Slide 77

Slide 77 text

Bundler Recommended I certainly recommend this - Bundler is certainly a great way of managing dependencies for any Ruby project.

Slide 78

Slide 78 text

Bundler Not Required That said, it’s not required - you can manage these things however you like. Bundler, after all, is a development tool - it will not have any impact on how people use your gem.

Slide 79

Slide 79 text

Bundler # Gemfile source :rubygems gemspec There’s no need to double up on gem dependency lists though - given we’re documenting that in our gemspec, Bundler can look at that instead - here’s a Gemfile example.

Slide 80

Slide 80 text

Bundler # Gemfile gemspec gem ‘mysql2’, :platform => :ruby gem ‘jdbc-mysql’, :platform => :jruby Sometimes, though, it’s necessary to be more specific than a gemspec allows - at least, for development dependencies. One example is different libraries for different rubies. If you’re doing this, then best to not list your development dependencies in the gemspec - after all, if anyone’s modifying your gem source, they’ll be using Bundler too.

Slide 81

Slide 81 text

Bundler rake release One last thing to note about Bundler is that it can provide a few helper rake tasks - the most useful of these being release, which builds and pushes a new gem version and tags the release in your git repo and pushes that tag to Github. It’s the tagging that’s particularly useful - the rest is easy enough to do manually.

Slide 82

Slide 82 text

Bundler # Rakefile Bundler::GemHelper. install_tasks To get those rake tasks, just add this line to your Rakefile.

Slide 83

Slide 83 text

Tools Of course, Bundler’s not the only tool around to help you manage and develop gems.

Slide 84

Slide 84 text

Tools Hoe Hoe has been around for years, and provides plugins to manage releasing your gem, as well as testing and documentation and I’m sure a few other bits and pieces as well.

Slide 85

Slide 85 text

Tools newgem newgem has also been around a while, and is built on top of hoe. It can even generate a website for your gem if you wish.

Slide 86

Slide 86 text

Tools Jeweler Jeweler’s not quite as heavy as either hoe or newgem - it just provides a generator for creating the essential gem project files, and some rake tasks to help manage releases. But you don’t need to use any of these - I recommend starting with a vanilla gemspec and see how far you can get.

Slide 87

Slide 87 text

Examples And examples of gemspecs - and gems - are everywhere. Look at the gems you’ve installed on your computer, or at code on Github. Don’t be afraid to read other peoples’ code - it’ll make you a better developer, whether or not you’re writing gems.

Slide 88

Slide 88 text

Examples bundle open kyiv A quick way to view gems is to use the `bundle open` command, which can open up any gem in your bundle in your preferred text editor.

Slide 89

Slide 89 text

Thank You Questions? Anyway, I think that’s enough from me - you can all start writing your own gems now! Does anyone have any questions?