Building the Josephine Gem
Recently I've been starting to mess around with Ruby Gems and try making one of my own. It is always a good feeling to see that the gem you made is being used by people across the world. Ahhhh... The beauty of open source software :).
Ok, so it's time for us to make our first Gem, Josephine (my girlfriend name AKA hopeless romantic). We are going to build it from scratch without using the bundler
gem which auto-populate the files and folders you'll need and initialize a git repository for you. A good reference for building gems is the RubyGems.org website. The RubyGems.org is the Ruby community's gem hosting service. I will publish my gem there and anybody can view it and install it from the website.
What is Josephine? well, it's a Ruby gem that calculates the number of files, total lines of code, comments, line spacing and average LOC.
% tree
.
├── josephine.gemspec
└── lib
└── josephine.rb
The convention when building a gem is to have one file in your lib directory with the same name as your gem. josephine.rb
is in charge of setting up your gem's code and API.
josephine.rb
class Josephine
def initialize(extension)
@extension = extension
extension_file
count_lines
end
def extension_file
if @extension == "-all".strip
ext = File.join("**", "*")
files = Dir.glob(ext)
else
ext = File.join("**", "*#{@extension}")
files = Dir.glob(ext)
end
end
def count_lines
num_files = 0 # Number of files
line_count = 0 # Number of lines of code
line_com = 0 # Number of lines of comments
space = 0
extension_file.each do |f|
next if f.index('vendor')
next if FileTest.directory?(f)
num_files += 1
i = 0
lines = []
File.new(f).each_line do |line|
if line.scrub.strip[0] == nil
space += 1
next
end
if line.scrub.strip[0] == '#'
line_com += 1
next
end
i += 1
end
line_count += i
end
puts ""
puts "------------------------------"
if @extension == "-all"
puts "#{num_files.to_s} files"
else
puts "#{num_files.to_s} files with #{@extension} extension."
end
puts "#{line_count.to_s} lines of code."
puts "#{(line_count.to_f/num_files.to_f).round(2)} LOC/file."
puts "#{line_com.to_s} lines of comments."
puts "#{space.to_s} line spacing."
puts "#{(space.to_f / num_files.to_f).round(2)} average line space / file."
end
end
In the josephine.gemspec
Gem::Specification.new do |s|
s.name = 'josephine'
s.version = '0.0.0'
s.date = '2015-04-05'
s.summary = "I <3 Josephine "
s.description = "count the number of lines of code in your project files"
s.authors = ["Cyrus Ghazanfar"]
s.email = 'cghazanfar10@gmail.com'
s.files = ["lib/josephine.rb"]
s.homepage =
'http://rubygems.org/gems/josephine'
s.executables << 'josephine'
s.license = 'MIT'
end
The gem specification file defines what’s in the gem, who made it, and the version of the gem. It is also your interface to communicate with Rubygems.org.
Since this gem will be run from the command line, we need to specify an executable file in a bin directory.
% tree
.
├── josephine.gemspec
└── bin
| └── josephine
└── lib
└── josephine.rb
In bin/josephine
require 'josephine'
ARGV.each do |ext|
puts Josephine.new(ext)
end
Here ARGV
is the argument passed to josephine when executing the gem from the command line.
For example, if I want to know the number of lines of code in all the files with .rb
extensions, then I will run
$ josephine .rb
.rb
is the ARGV
passed to josephine.
Now that you have created a gemspec, you can build a gem from it.
$ gem build josephine.gemspec
Successfully built RubyGem
Name: hola
Version: 0.0.0
File: josephine-0.0.0.gem
$ gem install ./josephine-0.0.0.gem
Successfully installed hola-0.0.0
1 gem installed
To share your gem on the RubyGems platform, you need to create an account and set up your computer with your RubyGems account via this command:
$ curl -u qrush https://rubygems.org/api/v1/api_key.yaml >
~/.gem/credentials; chmod 0600 ~/.gem/credentials
when you are finish with the setup, you can publish your gem to RubyGems by running this command:
$ gem push josephine-0.0.0.gem
Pushing gem to RubyGems.org...
Successfully registered gem: josephine (0.0.0)