Tag Archives: gemspec

Introduction
In this article I am going to explain how to create our own ruby gem using bundler. Bundler is a tool for managing Rubygems dependencies in Ruby libraries. But remember, Bundler isn’t just for Rails!

Did you know that you can use Bundler for not only gem dependency management but also for writing our own gems? It’s really easy to do this and Bundler provides a couple of things to help you along this path.

Why we need a gem?
Why should we create a gem? Can’t we just throw in some code into our other library and use that instead? Sure, we can do that. But then what if we want to use the code elsewhere, or we want to share it? This is why a gem is perfect. We can code our library and gem separately from each other and just have the library require the gem. If we want to use the gem in another library, then it’s just a tiny modification rather than a whole slew of copying.

Also: Sharing is caring.

Getting Started
First we need to install ruby(< 1.8.7) language, rubygems(< 1.3.6) & bundler gems.This guide was made using version 1.10.6 of bundler. We can follow along with other versions, but we might not get the exact same output. To check which version of bundler we currently have, lets run the following command:

   $bundler -v
  

If necessary, we can update to the newest version of Bundler by running ‘gem update bundler’.

To begin to create a gem using Bundler, use the bundle gem command like this:

   $bundler gem wavelabs_client_api
 

We call our gem wavelabs_client_api because this gem is going to communicate with wavelabs API Server, such as login, signup, Social Login..etc. Stay tuned. we need to follow the gem naming conventions. For more details visit this link

This command creates a scaffold directory for our new gem and, if we have Git installed, initializes a Git repository in this directory so we can start committing right away. If this is your first time running the bundle gem command, you will be asked whether you want to include a the CODE_OF_CONDUCT.md and LICENSE.txt files with your project. The files generated are:

  • Gemfile: Used to manage gem dependencies for our library’s development. This file contains a gemspec line meaning that Bundler will include dependencies specified in foodie.gemspec too. It’s best practice to specify all the gems that our library depends on in the gemspec.
  • Rakefile: Requires Bundler and adds the build, install and release Rake tasks by way of calling Bundler::GemHelper.install_tasks. The build task will build the current version of the gem and store it under the pkg folder, the install task will build and install the gem to our system (just like it would do if we gem install’d it) and release will push the gem to Rubygems for consumption by the public.
  • CODE_OF_CONDUCT.md: Provides a code of conduct that you expect all contributors to your gem to follow. Will only be included if you chose to have it included.
  • LICENSE.txt: Includes the MIT license. Will only be included if you chose to have it included.
  • .gitignore: (only if we have Git). This ignores anything in the pkg directory (generally files put there by rake build), anything with a .gem extension and the .bundle directory.
  • wavelabs_client_api.gemspec: The Gem Specification file. This is where we provide information for Rubygems’ consumption such as the name, description and homepage of our gem. This is also where we specify the dependencies our gem needs to run.
  • lib/wavelabs_client_api.rb: The main file to define our gem’s code. This is the file that will be required by Bundler (or any similarly smart system) when our gem is loaded. This file defines a module which we can use as a namespace for all our gem’s code. It’s best practice to put our code in…
  • lib/wavelabs_client_api: here. This folder should contain all the code (classes, etc.) for our gem. The lib/wavelabs_client_api.rb file is there for setting up our gem’s environment, whilst all the parts of it go in this folder. If our gem has multiple uses, separating this out so that people can require one class/file at a time can be really helpful.
  • lib/wavelabs_client_api/version.rb: Defines a WavelabsClientApi module and in it, a VERSION constant. This file is loaded by the wavelabs_client_api.gemspec to specify a version for the gem specification. When we release a new version of the gem we will increment a part of this version number to indicate to Rubygems that we’re releasing a new version.

There’s our base and our layout, now get developing! Now our gem directory structure as follows:

own_gem1

Open the .gemspec file and add the necessary details like author, license & files to be bundle..etc. I have modified the wavelabs_client_api.gemspec file as follows:

lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'wavelabs_client_api/version'

Gem::Specification.new do |spec|
  spec.name          = 'wavelabs_client_api'
  spec.version       = WavelabsClientApi::VERSION
  spec.authors       = ['sekhar']
  spec.email         = ['sekhar@nbostech.com']

  spec.summary       = %q{Simple Ruby Client Api for Wavelabs API Server.}
  spec.description   = %q{Simple Ruby Client Api for Wavelabs API Server.}
  spec.homepage      = 'TODO: Put your gem's website or public repo URL here.'
  spec.license       = 'MIT'

  # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
  # delete this section to allow pushing this gem to any host.
  # if spec.respond_to?(:metadata)
  #   spec.metadata['allowed_push_host'] = 'TODO: Set to 'http://mygemserver.com''
  # else
  #   raise &quot;RubyGems 2.0 or newer is required to protect against public gem pushes.&quot;
  # end

  spec.files         = Dir.glob(&quot;{bin,lib,spec}/**/*&quot;) + %w(LICENSE.txt README.md) + <code>git ls-files -z</code>.split('\x0')
  spec.bindir        = 'exe'
  spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
  spec.require_paths = ['lib']

  spec.add_dependency 'httmultiparty', '0.3.16'
  spec.add_dependency 'activemodel', '4.2.4'
  
  spec.add_development_dependency 'byebug'
  spec.add_development_dependency 'minitest'
  spec.add_development_dependency 'rspec'


  spec.add_development_dependency 'bundler', '~&gt; 1.10'
  spec.add_development_dependency 'rake', '~&gt; 10.0'
end

Note: There might be some formatting issues in above file in lines 24,37 & 38.

You need to add details to this file as per your requirement. If you didn’t already know this, the DSL for gem specifications is already pretty clean and straight-forward, there is no need to generate your gemspec using alternative tools.Your gemspec should run standalone, ideally with no additional dependencies. You can assume its FILE is located in the root of your project.

Here is the more documentation about .gemspec file.

As per my requirement I need httmultipart & activemodel gems as run time dependencies remaining gems are development dependencies. Now we can add our gem functionality under lib/wavelabs_client_api directory. If the functionality is not enough to fit into a single ruby file you can split the functionality by using ruby namespace/mixin concept.

After completing the functionality we need to require all the ruby files in lib/wavelabs_client_api.rb file as follows:

   require "wavelabs_client_api/version"

require "wavelabs_client_api/client/api/core/base_api"
require "wavelabs_client_api/client/api/core/auth_api"
require "wavelabs_client_api/client/api/core/users_api"
require "wavelabs_client_api/client/api/core/media_api"
require "wavelabs_client_api/client/api/core/social_api"


require "wavelabs_client_api/client/api/data_models/base_api_model"
require "wavelabs_client_api/client/api/data_models/login_api_model"
require "wavelabs_client_api/client/api/data_models/media_api_model"
require "wavelabs_client_api/client/api/data_models/member_api_model"
require "wavelabs_client_api/client/api/data_models/message_api_model"
require "wavelabs_client_api/client/api/data_models/social_accounts_api_model"
require "wavelabs_client_api/client/api/data_models/token_api_model"

module WavelabsClientApi
  # Your code goes here
end
  

In my gem I am using namespaces wavelabs_client_api/client/api/core to communicate with API Server and wavelabs_client_api/client/api/data_models to create & validate response objects. Now the gem directory structure as follows:

own_gem2

Stay Tuned! We are ready to release our first gem 🙂

Releasing the gem
If we haven’t already added git repository, we should add it & commit all the files for our repository:

    $git add .
    $git commit -m "The beginnings of the wavelabs_client_api gem"
  

This is because the wavelabs_client_api.gemspec file uses git ls-files to detect which files should be added to the gem when we release it.

The final step before releasing our gem is to give it a summary and description in the wavelabs_client_api.gemspec file.

Now we’re going to make sure that our gem is ready to be published. To do this, we can run rake build which will build a local copy of our gem and then gem install pkg/wavelabs_client_api-0.1.0.gem to install it. Then we can try it locally by running the commands that it provides. Once we know everything’s working, then we can release the first version.

To release the first version of our gem we can use the ‘rake release’ command, providing we have committed everything. This command does a couple of things. First it builds the gem to the pkg directory in preparation for a push to Rubygems.org.

Second, it creates a tag for the current commit reflecting the current version and pushes it to the git remote. It’s encouraged that we host the code on GitHub so that others may easily find it.If this push succeeds then the final step will be the push to Rubygems.org which will now allow other people to download and install the gem.

You’ll need to create an account on RubyGems.org. Visit the sign up page and supply an email address that you control, a handle (username) and a password.After creating the account, use your email and password when pushing the gem. (RubyGems saves the credentials in ~/.gem/credentials for you so you only need to log in once.)

If we want to release a second version of our gem, we should make our changes and then commit them to GitHub. Afterwards, we will bump the version number in lib/wavelabs_client_api/version.rb to whatever we see fit, make another commit to GitHub with a useful message such as “bumped to 0.0.2” and then run rake release again.

Conclusion:

In this article I have explained how to create our own ruby gem. I have created my first gem and it is available on rubygems.org. gem name is ‘wavelabs_clien_api’. Still I am refining my first gem so that it has many versions and some versions are yanked. Source code is available on github

I will cover how to write tests for our own gem & creating a generator in my next article. Thanks for reading this article!