What are gems made out of? Code. (dammit Avi…)
I realized the other day that, while I’ve been using gems for awhile now I didn’t actually know what goes into building and publishing one. Let’s fix that.
What is a Gem?
A gem is the standard format for distributing Ruby programs and libraries, typically through the RubyGems package manager.
OK, so let’s make one.
Fine (pushy…).
I started out writing out the steps to properly set up your file structure and build your gem. It looked something like this:
I.Create a directory with the name of your gem.
It should look something like this:
1 2 3 4 |
|
Ruby Gem Naming convention as per RubyGems.org:
1 2 3 4 5 |
|
II. WRITE YO CODE!
And put it in the ‘lib’ folder. The convention is to have one Ruby file with the name of your gem, since that will be what is loaded when someone requires your gem. This file is in charge of setting up your gem’s code and application program interface.
Require additional files:
- These should go into a subfolder within lib named for the gem and required in your main gem file. These dependencies will also be listed in your gem spec. We’ll get to that in a bit.
1 2 3 4 |
|
III. Build the gemspec.
The gem spec contains all the information about your gem. Who made it, what it’s for, its version, homepage, yada yada yada. It’s al in the gemspec. You can even make a gem without filling out the required attributes of your gem in a gem spec file. So it’s kinda important.
IV. Build the gem:
1
|
|
V. Install the gem locally.
1
|
|
VI. Test yo ish!
You don’t want to send out non-functional code with all your contact info in it. Include a test suite and documentation.
1 2 3 4 5 6 7 8 9 10 11 |
|
1 2 3 4 5 6 |
|
VII. Document your code with RDoc, Yard, or something similar.
VIII. Publish!
Create an account at ruby gems.org.
Setup your account on your computer
1
|
|
Push your gem to the interwebs.
1
|
|
Now Ignore All of That and Do This Instead:
Why? because it’s faster, easier, and idiot-proof.
1
|
|
Oh, look! It made just about everything you need and it even included hints of what to put where in the files that Bundler created for you.
1 2 3 4 5 6 7 8 9 10 11 |
|
Hey! Look! A TODO list!
1 # coding: utf-8
2 lib = File.expand_path('../lib', __FILE__)
3 $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4 require 'test_gem/version'
5
6 Gem::Specification.new do |spec|
7 spec.name = "test_gem"
8 spec.version = TestGem::VERSION
9 spec.authors = ["user_name"]
10 spec.email = ["user_email@some_mail.com"]
11
12 spec.summary = %q{TODO: Write a short summary, because Rubygems requires one.}
13 spec.description = %q{TODO: Write a longer description or delete this line.}
14 spec.homepage = "TODO: Put your gem's website or public repo URL here."
15 spec.license = "MIT"
16
17 # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
18 # delete this section to allow pushing this gem to any host.
19 if spec.respond_to?(:metadata)
20 spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
21 else
22 raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
23 end
24
25 spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26 spec.bindir = "exe"
27 spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28 spec.require_paths = ["lib"]
29
30 spec.add_development_dependency "bundler", "~> 1.10"
31 spec.add_development_dependency "rake", "~> 10.0"
32 spec.add_development_dependency "rspec"
33 end
Now write your ruby, fill out your gem spec and readme, build your gem, write some tests, test your gem, and publish your fancy, new red rock.
Here’s the not all that useful gem that I built for the purposes of this gemsperiment:
1 require "poezix/version"
2
3 class String
4 def upon_a_midnight_dreary
5 if self == "once"
6 1.times do
7 yield
8 end
9 elsif self == "twice"
10 2.times do
11 yield
12 end
13 elsif self == "thrice"
14 3.times do
15 yield
16 end
17 else
18 raise "Mayhaps an Integer you seek?"
19 end
20 end
21 end
22
23
24 class Integer
25 def upon_a_midnight_dreary
26 self.times do
27 yield
28 end
29 end
30 end
31
32
33
34 def quoth(phrase = "Nevermore")
35 puts phrase.upcase + "!!!"
36 end
37
38
39 #Generates filler content from a text randomly selected from one of 42 poems/short stories.
40 #Takes an arguement to determine the number of line returned.
41
42 def poesem_ipsum(number_of_lines = "full")
43 all_texts = Dir[File.dirname(__FILE__) + "/texts/*.txt"]
44 number_of_texts = all_texts.size
45 selection = rand(1..number_of_texts)
46
47 text = File.open(all_texts[selection]).readlines #An Array
48
49 if number_of_lines == "full"
50 number_of_lines = text.count - 1
51 end
52
53 text[0..number_of_lines].join
54 end
Sources:
[Engineering Lunch Series] Step-by-Step Guide to Building Your First Ruby Gem https://quickleft.com/blog/engineering-lunch-series-step-by-step-guide-to-building-your-first-ruby-gem/