Now that your engines are packaged as gems, and versioned, they can easily be loaded in your application using Bundle. But if we want Bundle to find them, they need to be available from somewhere online!
How do we do that?
To push your gems online, you have two solutions: Public and Private. Your choice really depends on what kind of work you are doing, and if you are working on an open-source engine or on an engine that’s supposed to stay private.
If you want to share your engine with the world, your life will be easy as pie. That’s what karma is all about, right? If you are ready to share it, you can just use RubyGems. That’s it!
RubyGems stores all gems for free, and you can upload yours there too. Anyone will be able to use it and see your code, so if that’s not a problem for you, go for it!
Unfortunately, sharing your gems is not always possible. Even if you want to, you might not have permission to share your code. The corporate world doesn’t like it when you share their secrets! That’s understandable, so we need another solution… but don’t expect it to be free (it’s fine, the company will pay…).
Lucky us… if RubyGems can do it, why can’t we? Other people have thought about this too, and that’s probably how Gemfury was born.
Gemfury gives you a gem server where you can store private and public gems, and you control if you want a gem to be public or remain private. Unfortunately, Gemfury is not free; you pay per user for any private gems.
So if Gemfury is too pricey for you, how about making our own? It will have a cost too, but it is going to be a small flat fee. The only thing we will need is a server. Any cheap provider like Digital Ocean or Linode will do. The server will just store packaged gems and send them when someone runs the bundle install
command. Nothing too intense. All we need is for it to be accessible remotely.
Got a server? Good! But we still have to set up a gem server. The good news is that some people have created useful gems that we can use to set up a gem server (irony at its best). We will show you how to build a private gem server with Gem in a Box on a Digital Ocean Droplet. You can get a server and follow the steps, but honestly, it’s not that hard, so reading should be enough to understand how it works.
You can use any server that you have access to. If you want to get your own Digital Ocean Droplet, you can sign up here. This is an affiliate link and you will get a credit of $10 if you use it. This means you can try building your private gem server for free! (Devblast will also get a commission if you become a regular user.)
Let’s get started!
Thanks to this neat little gem, Gem in a Box, we can easily create a simple gem server. The following commands will be run from a Digital Ocean Droplet, and we will use RVM to install Ruby. We will put the Gem in a Box web application in /var/www/gemserver
and store the actual gems in /var/devblast/gems/
(Don’t forget that this is our personal server and nobody else has access to it).
\curl -sSL https://get.rvm.io | bash -s stable --ruby
source ~/.rvm/scripts/rvm
rvm requirements
gem install geminabox --no-doc
mkdir /var/www/gemserver
mkdir home/your_folder/gems
/var/www/gemserver/config.ru
Create /var/www/gemserver/config.ru
by running
touch /var/www/gemserver/config.ru
and populate it with the contents of Listing 1. Don’t forget to change A_VERY_SECRET_KEY
to something very secret.
/var/www/gemserver/config.ru
require "rubygems"
require "geminabox"
Geminabox.data = "/home/your_folder/gems" # ... or wherever
use Rack::Auth::Basic, "Blast Secret Gem Server" do |username, password|
username == 'blast' && password == 'A_VERY_SECRET_KEY'
end
run Geminabox::Server
If you want to keep your server open, you can remove HTTP authentication by removing these lines:
use Rack::Auth::Basic, "Blast Secret Gem Server" do |username, password|
username == 'blast' && password == 'A_VERY_SECRET_KEY'
end
sudo chown -R www-data:www-data /var/www/gemserver
We’re using Puma because we like it and because Rails has now made it the default.
gem install puma
Before running the command below, be sure that you are in the /var/www/gemserver
we created earlier. Then just launch the server:
puma --port 9292 config.ru -d
If you want to have more details about what’s going on with puma
while running it, just don’t run the server as a daemon and remove the -d
parameter. It can be useful to debug any issues present in our config.ru
.
So how do we push gems now? Let’s push the Core
module to see how it works. The following commands can be run from your local computer.
First, navigate to blast_crm/engines/core
.
gem build blast_core.gemspec
gem inabox blast_core-0.0.1.gem
On your gem server you can check the presence of the gem in the folder you have configured via the Geminabox.data
variable in the config.ru
file. Just have a look at the folder and our blast_core-0.0.1
should be present!
rm blast_core-0.0.1.gem
And that’s it! Our gems are on our private gem server.
Adding the source to the default sources will allow us to query for our gems from anywhere on your computer.
gem sources -a http://blast:A_VERY_SECRET_KEY@[your_server]:9292/
You can use the gem sources
command to see all the sources listed, the one we added is now included in this one.
gem install blast_core
And you should see an output that shows you that your gem was installed.
We just added our gem server as a source for the rubygems
gem. Now, let’s see how we can load gems in your Rails application using Bundle.
Gemfile
source "https://rubygems.org"
source "http://blast:A_VERY_SECRET_KEY@[your_server]:9292"
.
.
.
Rails 5.2 gives us an amazing little tool called credentials
to securely store various secret keys. To use it we will need to update it (you can use any editor your like) by running the following command:
EDITOR=vi rails credentials:edit
Now simply add the following line at the bottom of the file:
gem_server_key: A_VERY_SECRET_KEY
Finally, tell your Gemfile to look for your key in the credentials file:
Gemfile
source "https://rubygems.org"
source "http://blast:#{Rails.application.credentials.gem_server_key}@blast.com:9292"
.
.
.
Remove the path option for the Core
module inside your Gemfile, and add the gem:
Gemfile
.
.
.
gem 'blast_core'
bundle update
You should see your usual bundle output that includes our gem.
Now that our private Gem server is ready, it’s time to push our modules! But first, let’s update the versions. We’re going to update all our modules to 1.0.0
and officially release them! Do the four following steps for each module: Core
, Contacts
and Tasks
and replace {module}
with the appropriate module name.
blast_crm/engines/{module}/lib/blast/{module}/version.rb
module Blast
module Core
VERSION = '1.0.0'
end
end
gem build blast_{module}.gemspec
gem inabox blast_{module}-1.0.0.gem
rm blast_{module}-1.0.0.gem
In this chapter we learned about where to publish our engines and use the published gems in our production application.
Next, we will learn how to create our own gem server.