0

How to build your own GEM in Ruby

When you are a Ruby developer you are not unfamiliar with the Gem. Have you ever wanted to have a really useful gem that people can use, the author is yourself? Today, I will show you how to create a Gem for Ruby on Rails. Now let start a simple gem that call "simple_hello_world"

YOUR FIRST GEM

I will start with a Gem, the name is quite simple just "simple_hello_world". You can give your name a unique name or some of your own stamp, preferably if it is useful, then put a name reminiscent of the Gem. Naming guidelines are guided by basic recommendations . Naming the directory and file name will be basically like this, including a .rb file located in the lib directory, and a .gemspec file in the directory .lib

tree
.
├── lib
│       └── simple_hello_world.rb
└── simple_hello_world.gemspec

Now, we will write the demo code for our Gem. Inside the filelib/simple_hello_world:

class SimpleHelloWorld
  def self.hi language = "english"
     puts "Hello world!"
  end
end

The .gemspec file defines the attributes of the gem, the author, as well as the version, description, and loaded files. This is also an interface to RubyGems.org . All the information you see on the gem site is defined from this .gemspec file.

Gem::Specification.new do |s|
  s.name        = 'simple_hello_world'
  s.version     = '0.0.0'
  s.date        = '2017-09-25'
  s.summary     = "simple_hello_world"
  s.description = "A simple hello world gem"
  s.authors     = ["Sopheak"]
  s.email       = 'your_mail@something.com'
  s.files       = ["lib/simple_hello_world.rb", "lib/simple_hello_world/translator.rb"]
  s.homepage    =
    'http://rubygems.org/gems/simple_hello_world'
  s.license       = 'MIT'
end

The description may be longer than the text you see in my example, as long as it can match the condition /^== [A-Z]/ then the description will be run through the RDoc's markup formatter to display on the RubyGems web site. Are you very familiar? This gemspec as well as Ruby, you can change the wrap scripts to create the file names, and also the version number. There are a lot of fields to include in the .gemspec file, which you can see in the reference guides of ruby ​​gems. After creating a gem, you can build gem from there. And then install this gem to test the functions you just wrote

gem build simple_hello_world.gemspec 
  Successfully built RubyGem
  Name: simple_hello_world
  Version: 0.0.0
  File: simple_hello_world-0.0.0.gem
gem install ./simple_hello_world-0.0.0.gem
Successfully installed simple_hello_world-0.0.0
Parsing documentation for simple_hello_world-0.0.0
Installing ri documentation for simple_hello_world-0.0.0
Done installing documentation for simple_hello_world after 0 seconds
1 gem installed

Can install almost the same as the "g" and then it! Of course, the smoke test is not finished, now you can require gem and test your product okay. Here I test on rails console

 require 'simple_hello_world'
 => true 
2.3.0 :002 > SimpleHelloWorld.hi
Hello world!

It looks like the product. A small note when you use the previous Ruby version 1.9.2 is to start the session with irb -ruby gems or require ruby gems after launch irb. Now you can share your Gem product with the Ruby community.

curl -u bapboy18  https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials; chmod 0600 ~/.gem/credentials
Enter host password for user 'phornsopheak':

Push gem up rubygems:

gem push simple_hello_world-0.0.0.gem 
Pushing gem to https://rubygems.org...
Successfully registered gem: simple_hello_world (0.0.0)

At this step, you may need to register / login to the Ruby gem account. Only within a short period of time after the Gem is pushed (under 1 minute), this Gem can be installed from anyone.

gem list -r simple_hello_world

*** REMOTE GEMS ***

simple_hello_world (0.0.0)
gem install simple_hello_world
Successfully installed simple_hello_world-0.0.0
Parsing documentation for simple_hello_world-0.0.0
Done installing documentation for simple_hello_world after 0 seconds
1 gem installed

Install as Gem "short" like this! and you can test it now:

irb -Ilib -rsimple_hello_world
2.3.0 :001 > SimpleHelloWorld.hi "english"
 => "hello world" 
2.3.0 :002 > SimpleHelloWorld.hi "spanish"
 => "hola mundo" 

Running seems to function properly. Sharing code with Ruby and RubyGems is easy!

REQUIRING MORE FILES

When expanding the Gem function, it is very inconvenient to put all the files into one file. In the next section, I will cover how the file extension works, as well as how Gem functions work. Suppose we have more functions to add in the file simple_hello_world.rb

class SimpleHelloWorld
  def self.hi language = "english"
    translator = Translator.new(language)
    translator.hi
  end
end

class SimpleHelloWorld::Translator
  def initialize(language)
    @language = language
  end

  def hi
    case @language
    when "spanish"
      "hola mundo"
    else
      "hello world"
    end
  end
end

There seems to be too much code in the same file, which makes the code really messy when you have more code. Now we will separate the Translator class into a separate file. As mentioned earlier, the root file is responsible for loading the gem code, the other code files will be placed in the directory with the same name as the root file. Here, I put the directory simple_hello_world, of course, inside the lib directory .

tree
.
├── lib
│   ├── simple_hello_world
│   │   └── translator.rb
│   └── simple_hello_world.rb

Now, the Translator class is in the lib / simple_hello_world directory , and the code in translator.rb this file is an extension:

class SimpleHelloWorld::Translator
  def initialize(language)
    @language = language
  end

  def hi
    case @language
    when "spanish"
      "hola mundo"
    else
      "hello world"
    end
  end
end

Put more lines of code in the simple_hello_world.rb file so that it can load the code in the extension:

class SimpleHelloWorld
  def self.hi language = "english"
    translator = Translator.new(language)
    translator.hi
  end
end

require "simple_hello_world/translator"

And in the .gemspec file do not forget to declare the file you created:

Gem::Specification.new do |s|
  ...
  s.files       = ["lib/simple_hello_world.rb", "lib/simple_hello_world/translator.rb"]
  ...
end

Test results on rails console :

irb -Ilib -rsimple_hello_world
2.3.0 :001 > SimpleHelloWorld.hi
 => "hello world" 
2.3.0 :002 > SimpleHelloWorld.hi "spanish"
 => "hola mundo" 

If you add files to your gems, remember to declare them in the gemspec files before pushing them up as a new gem. Or it can be declared so that it can be identified automatically as just a dynamic gemspec . Adding multiple directories and adding more code when building the Gem also follows a similar process. Split your files when it makes sense. Make your code so scientific that you do not get confused by looking at the code.

ADDING AN EXECUTABLE

mkdir bin
touch bin/simple_hello_world
chmod a+x bin/simple_hello_world
ruby -Ilib ./bin/simple_hello_world 
hello world
 ruby -Ilib ./bin/simple_hello_world spanish
hola mundo
head -4 simple_hello_world.gemspec 
Gem::Specification.new do |s|
  s.name        = 'simple_hello_world'
  s.version     = '0.0.1'
  s.executables << 'simple_hello_world'

All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí