Skip to content

Instantly share code, notes, and snippets.

@trishume trishume/
Created Jun 14, 2014

What would you like to do?
Ruby Gem Presentation

Creating a gem in 10m

First we will create a new gem scaffold using the bundler gem that comes with Ruby.

$ bundle gem tofu
$ cd tofu
$ subl .

Now we can edit the gemspec file to add metadata to our gem.

So lets actually code something, how about being able to count all the lines of code we have written.

# lib/tofu.rb
require "tofu/version"

module Tofu
  class LineCounter
    def initialize(base_dir)
      @base_dir = base_dir

    def code_files(exts)
      glob = File.join(File.expand_path(@base_dir), "**/*.{#{exts}}")
      Dir[glob].reject {|f| }

    def lines(file)

    def all_lines(exts)
      files = code_files(exts)
      line_count = {|f| lines(f)}.inject(:+)
      file_count = files.size
      return line_count, file_count

Now we can test this in irb

$ irb -Ilib
>> require "tofu"
>> t ="~/Box/Dev")
>> t.all_lines('rb,py')

But we don't want to use irb, we want a cool executable like bundler. For this we create something in the bin folder.

#!/usr/bin/env ruby
require "tofu"

t =[0] || Dir.pwd)
lines, files = t.all_lines(ARGV[1] || 'rb,py,m,cpp,h')

puts "Found #{lines} lines across #{files} files."

Now see in the gemspec, bundler won't recognize our files until we add them to git.

$ git add -A
$ git commit -m "Initial stuff"

Now we can try out our command.

$ bundle
$ bundle exec tofu
$ bundle exec tofu ~/Box/Dev
$ bundle exec tofu ~/Box/Dev rb,py

Now lets add a dependency to make things snazzy. We just add a line to our gemspec to declare it and then use it in our executable file.

# tofu.gemspec
spec.add_runtime_dependency 'colored'
# bin/tofu
require "colored"
puts "Found #{} lines across #{} files."

For extra credit let's add snazziness, a unix command can trivially count lines but we can count lines of code by stripping empty lines and comments.

def lines(file)
  count = 0
  IO.foreach(file) do |line|
    # TODO: fix stupid UTF-8 stuff, Oh Lord Matz, forgive me for using rescue nil
    count += 1 unless line.empty? || (line =~ /^\S*(#|\/\/)/) rescue nil

Now we want to be able to install this on our computer and our friends so lets package it.

$ rake build
$ rake install
$ rake release # don't run this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.