Gems are Ruby’s way of packaging applications or libraries so they can be easily shared. https://rubygems.org/ is a place where people host their gems to make them publicly available.
Installing a gem from https://rubygems.org/ is very easy:
1 gem install awesome_print
Once you install the gem, you might want to know where it was installed. You can find some information about your gem install by using gem env:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 $ gem env RubyGems Environment: - RUBYGEMS VERSION: 18.104.22.168 - RUBY VERSION: 2.0.0 (2015-12-16 patchlevel 648) [universal.x86_64-darwin15] - INSTALLATION DIRECTORY: /Library/Ruby/Gems/2.0.0 - RUBY EXECUTABLE: /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby - EXECUTABLE DIRECTORY: /usr/local/bin - RUBYGEMS PLATFORMS: - ruby - universal-darwin-15 - GEM PATHS: - /Library/Ruby/Gems/2.0.0 - /Users/adrian/.gem/ruby/2.0.0 - /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/gems/2.0.0 - GEM CONFIGURATION: - :update_sources => true - :verbose => true - :backtrace => false - :bulk_threshold => 1000 - REMOTE SOURCES: - https://rubygems.org/
The part we care the most about at this time is GEM PATHS. I can see where awesome_print was installed:
1 2 3 $ ls -l /Library/Ruby/Gems/2.0.0/gems/ total 0 drwxr-xr-x 13 root wheel 442B Oct 3 09:32 awesome_print-1.7.0/
Another interesting thing is what happens when you require a awesome_print. It can be seen using irb:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 irb(main):003:0> puts $LOAD_PATH /Library/Ruby/Site/2.0.0 /Library/Ruby/Site/2.0.0/x86_64-darwin15 /Library/Ruby/Site/2.0.0/universal-darwin15 ... => nil irb(main):004:0> require 'awesome_print' => true irb(main):005:0> puts $LOAD_PATH /Library/Ruby/Gems/2.0.0/gems/awesome_print-1.7.0/lib /Library/Ruby/Site/2.0.0 /Library/Ruby/Site/2.0.0/x86_64-darwin15 /Library/Ruby/Site/2.0.0/universal-darwin15 ... => nil
You can see that after requiring awesome_print a new path was added to $LOAD_PATH: /Library/Ruby/Gems/2.0.0/gems/awesome_print-1.7.0/lib.
Creating a gem
We’ve learned how to use a gem. Now, lets learn how to create one of our own. The basic structure of a gem is the following:
1 2 3 4 /some-folder |--my_awesome_gem.gemspec |--/lib |--my_awesome_gem.rb
If the name of your gem has multiple words, use underscore(_) to separate words, the dash(-) is reserved for separating directories. lib/my_awesome_gem.rb is the entry point for the gem. You can include whatever code you want there. My gem will just extend the Integer class:
1 2 3 4 5 class Integer def say_awesome puts 'Awesome' end end
For the gem to be valid we also need to fill my_awesome_gem.gemspec:
1 2 3 4 5 6 7 8 9 10 11 Gem::Specification.new do |s| s.name = 'my_awesome_gem' s.version = '0.0.0' s.summary = 'Say awesome' s.description = 'Extend Integer so it can say awesome' s.authors = ['Adrian Ancona'] s.email = 'email@example.com' s.files = ['lib/my_awesome_gem.rb'] s.homepage = 'http://i.dont.have.one' s.license = 'MIT' end
Most of the fields are straight forward, but there is one that is very important to get right. s.files needs to contain all the files that are being used by your gem or it won’t work. This step is very error prone, so the best you can do is automate it. Since the gemspec file uses ruby, you can write some code that gets all ruby files and adds them to s.files.
One we have our code and gemspec ready, we can build the gem:
1 gem build my_awesome_gem.gemspec
You should get a message saying that the gem was build successfully. You will also get a file my_awesome_gem-0.0.0.gem. Now, we can install the gem to make it available anywhere in our system:
1 gem install my_awesome_gem-0.0.0.gem
Now, we can test our gem:
1 2 3 4 5 6 [anovelo@localhost awesome-gem]$ irb irb(main):001:0> require 'my_awesome_gem' => true irb(main):002:0> 1.say_awesome Awesome => nil
This is a very basic gem, but your gem can get as complicated as you want. With this information you should be able to package and share it with the whole world.