pat allan. cut and polish: crafting gems

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

Upload: svitla-systems-inc

Post on 09-May-2015

2.586 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Pat Allan. Cut and Polish: Crafting Gems

Cut and PolishA Guide to

Crafting GemsGood afternoon everyone - I hope you’re all ready to learn about how to write gems!

Page 2: Pat Allan. Cut and Polish: Crafting Gems

Pat Allan@pat

freelancing-gods.comMy 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.

Page 3: Pat Allan. Cut and Polish: Crafting Gems

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

Page 4: Pat Allan. Cut and Polish: Crafting Gems

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

Page 5: Pat Allan. Cut and Polish: Crafting Gems

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

Page 6: Pat Allan. Cut and Polish: Crafting Gems

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

Page 7: Pat Allan. Cut and Polish: Crafting Gems

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

Page 8: Pat Allan. Cut and Polish: Crafting Gems

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

Page 9: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 10: Pat Allan. Cut and Polish: Crafting Gems

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?

Page 11: Pat Allan. Cut and Polish: Crafting Gems

noun

a package manager for Ruby libraries.

|ˈro͞obējemz|rubygems

Well, it’s essentially a package manager for gems.

Page 12: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 13: Pat Allan. Cut and Polish: Crafting Gems

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

Page 14: Pat Allan. Cut and Polish: Crafting Gems

Why?

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

Page 15: Pat Allan. Cut and Polish: Crafting Gems

Why?

easy to installThey’re also pretty easy to install - at least, in most cases.

Page 16: Pat Allan. Cut and Polish: Crafting Gems

Why?

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

Page 17: Pat Allan. Cut and Polish: Crafting Gems

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

Page 18: Pat Allan. Cut and Polish: Crafting Gems

History

2003rubyforge.org

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

Page 19: Pat Allan. Cut and Polish: Crafting Gems

History

2004rubygems

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

Page 20: Pat Allan. Cut and Polish: Crafting Gems

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

Page 21: Pat Allan. Cut and Polish: Crafting Gems

History

gems were magical

And there was still some mystery about constructing gems.

Page 22: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 23: Pat Allan. Cut and Polish: Crafting Gems

History

2009gemcutter.org

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

Page 24: Pat Allan. Cut and Polish: Crafting Gems

History

anyone can publish

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

Page 25: Pat Allan. Cut and Polish: Crafting Gems

History

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

Page 26: Pat Allan. Cut and Polish: Crafting Gems

GemspecsThat’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.

Page 27: Pat Allan. Cut and Polish: Crafting Gems

Gemspecs

kyiv.gemspecEvery 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.

Page 28: Pat Allan. Cut and Polish: Crafting Gems

# kyiv.gemspecGem::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.

Page 29: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 30: Pat Allan. Cut and Polish: Crafting Gems

Naming

# name‘will_paginate’# requiringrequire ‘will_paginate’# Class/ModuleWillPaginate

Also: keep it lowercase, and as a general rule, use underscores for word separation...

Page 31: Pat Allan. Cut and Polish: Crafting Gems

Naming

# name‘cucumber-rails’# requiringrequire ‘cucumber/rails’# Class/ModuleCucumber::Rails

... and hyphens for namespacing. These are not rules, just recommendations - I’ve failed to follow them in the past, as have many others.

Page 32: Pat Allan. Cut and Polish: Crafting Gems

Versions

s.version = ‘0.0.1’

Next is the version number of your gem.

Page 33: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 34: Pat Allan. Cut and Polish: Crafting Gems

Versions

Major VersionsMajor 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.

Page 35: Pat Allan. Cut and Polish: Crafting Gems

Versions

Minor VersionsMinor 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.

Page 36: Pat Allan. Cut and Polish: Crafting Gems

Versions

Release Versions

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

Page 37: Pat Allan. Cut and Polish: Crafting Gems

Versions

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

Page 38: Pat Allan. Cut and Polish: Crafting Gems

Versions

# lib/kyiv/version.rbmodule Kyiv VERSION = ‘0.0.1’end

Such a file would look something like this - with a constant containing our version number.

Page 39: Pat Allan. Cut and Polish: Crafting Gems

Versions

# kyiv.gemspecrequire ‘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.

Page 40: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 41: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 42: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 43: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 44: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 45: Pat Allan. Cut and Polish: Crafting Gems

Files

Kyiv::Touristlib/kyiv/tourist.rb

Kyiv::Translatorlib/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.

Page 46: Pat Allan. Cut and Polish: Crafting Gems

Files

# Don’t do thislib/kyiv.rblib/tourist.rblib/translator.rb

You don’t want to do anything like this - because what happens if there’s also a gem named ‘tourist’?

Page 47: Pat Allan. Cut and Polish: Crafting Gems

Information Files

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

Page 48: Pat Allan. Cut and Polish: Crafting Gems

Information Files

LICENCEDon’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.

Page 49: Pat Allan. Cut and Polish: Crafting Gems

Information Files

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

Page 50: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 51: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 52: Pat Allan. Cut and Polish: Crafting Gems

Test Files

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

Page 53: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 54: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 55: Pat Allan. Cut and Polish: Crafting Gems

# kyiv.gemspecGem::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.

Page 56: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 57: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 58: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 59: Pat Allan. Cut and Polish: Crafting Gems

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!

Page 60: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 61: Pat Allan. Cut and Polish: Crafting Gems

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!

Page 62: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 63: Pat Allan. Cut and Polish: Crafting Gems

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

Page 64: Pat Allan. Cut and Polish: Crafting Gems

# run testsrake spec

# generate documentationrake yard

# default task should run testsrake

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.

Page 65: Pat Allan. Cut and Polish: Crafting Gems

PublishingSo, 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?

Page 66: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 67: Pat Allan. Cut and Polish: Crafting Gems

Gem Files

.gem == .tarIf 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.

Page 68: Pat Allan. Cut and Polish: Crafting Gems

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!

Page 69: Pat Allan. Cut and Polish: Crafting Gems

Publishing

PermanentIt’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.

Page 70: Pat Allan. Cut and Polish: Crafting Gems

Publishing

(Don’t) YankHowever, 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.

Page 71: Pat Allan. Cut and Polish: Crafting Gems

Publishing

MRI 1.9 CautionFor 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.

Page 72: Pat Allan. Cut and Polish: Crafting Gems

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

Page 73: Pat Allan. Cut and Polish: Crafting Gems

Community

SupportFirstly, 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.

Page 74: Pat Allan. Cut and Polish: Crafting Gems

Community

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

Page 75: Pat Allan. Cut and Polish: Crafting Gems

Community

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

Page 76: Pat Allan. Cut and Polish: Crafting Gems

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

Page 77: Pat Allan. Cut and Polish: Crafting Gems

Bundler

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

Page 78: Pat Allan. Cut and Polish: Crafting Gems

Bundler

Not RequiredThat 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.

Page 79: Pat Allan. Cut and Polish: Crafting Gems

Bundler

# Gemfilesource :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.

Page 80: Pat Allan. Cut and Polish: Crafting Gems

Bundler

# Gemfilegemspec

gem ‘mysql2’, :platform => :rubygem ‘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.

Page 81: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 82: Pat Allan. Cut and Polish: Crafting Gems

Bundler

# RakefileBundler::GemHelper. install_tasks

To get those rake tasks, just add this line to your Rakefile.

Page 83: Pat Allan. Cut and Polish: Crafting Gems

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

Page 84: Pat Allan. Cut and Polish: Crafting Gems

Tools

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

Page 85: Pat Allan. Cut and Polish: Crafting Gems

Tools

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

Page 86: Pat Allan. Cut and Polish: Crafting Gems

Tools

JewelerJeweler’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.

Page 87: Pat Allan. Cut and Polish: Crafting Gems

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

Page 88: Pat Allan. Cut and Polish: Crafting Gems

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.

Page 89: Pat Allan. Cut and Polish: Crafting Gems

Thank YouQuestions?

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