Write a gem in Ruby using Jeweler
Steps.
- Install gem called jeweler
$ gem install jeweler
Fetching: jeweler-1.6.4.gem (100%)
Successfully installed jeweler-1.6.4
1 gem installed
Installing ri documentation for jeweler-1.6.4...
Installing RDoc documentation for jeweler-1.6.4...
To execute the command, first checkout the options
$ jeweler --help
Now generate a new project using the command jeweler.
$ jeweler hello_gem
No github.user found in ~/.gitconfig. Please tell git about your GitHub account (see http://github.com/blog/180-local-github-config for details). For example: git config --global github.user defunkt
ERROR: The above command came up with an error.
To fix the user
$ git config --global github.user defunkt
$ git config --global github.token 6ef8395fecf207165f1a82178ae1b984
- replace defunkt and 6ef8395fecf207165f1a82178ae1b984
with your user and token respectively.
- To get the token from the Github
On Github > Account Seetings > Account Admin > API token: Your token is ***********
Rerun the jeweler command to create a new project
- By default the test script are generated for shoulda
- I am familiar with Rspec so I chose Rspec for my testing.
$ jeweler hello_gem --rspec
create .gitignore
create Rakefile
create Gemfile
create LICENSE.txt
create README.rdoc
create .document
create lib
create lib/hello_gem.rb
create spec
create spec/spec_helper.rb
create spec/hello_gem_spec.rb
create .rspec
Jeweler has prepared your gem in ./hello_gem
The structure of the directories are
$ tree
.
└── hello_gem
├── Gemfile
├── lib
│ └── hello_gem.rb
├── LICENSE.txt
├── Rakefile
├── README.rdoc
└── spec
├── hello_gem_spec.rb
└── spec_helper.rb
3 directories, 7 files
hello_gem doesnt have the rspec gem yet, so in the Gemfile
group :test do
gem 'rspec', "~> 2.3.0"
end
Run the bundle install command to install the rspec gem
$ bundle install
To know all the rake commands that can run,
$ rake -T
rake build # Build gem into pkg/
rake clobber_rdoc # Remove rdoc products
rake console[script] # Start IRB with all runtime dependencies loaded
rake gemcutter:release # Release gem to Gemcutter
rake gemspec # Generate and validate gemspec
rake gemspec:debug # Display the gemspec for debugging purposes, as jeweler knows it (not from the filesystem)
rake gemspec:generate # Regenerate the gemspec on the filesystem
rake gemspec:release # Regenerate and validate gemspec, and then commits and pushes to git
rake gemspec:validate # Validates the gemspec on the filesystem
rake git:release # Tag and push release to git.
rake install # Build and install gem using `gem install`
rake rcov # Run RSpec code examples
rake rdoc # Build the rdoc HTML Files
rake release # Release gem
rake rerdoc # Force a rebuild of the RDOC files
rake spec # Run RSpec code examples
rake version # Displays the current version
rake version:bump:major # Bump the major version by 1
rake version:bump:minor # Bump the a minor version by 1
rake version:bump:patch # Bump the patch version by 1
rake version:write # Writes out an explicit version.
Before we start with the gem we need a version to it.
$ rake version:write MAJOR=0 MINOR=1 PATCH=0
Updated version: 0.1.0
To know the current version
$ rake version
Current version: 0.1.0
Now install the gem
$ rake install
rake aborted!
"FIXME" or "TODO" is not a description
Tasks: TOP => install => build
(See full trace by running task with --trace)
NOTE: If you get this error, then open the Rakefile
Change the lines from
gem.summary = %Q{TODO: one-line summary of your gem}
gem.description = %Q{longer description of your gem}
to
gem.summary = "one-line summary of your gem"
gem.description = "longer description of your gem"
Now try again
$ rake install
Successfully built RubyGem
Name: hello_gem
Version: 0.1.0
File: hello_gem-0.1.0.gem
Executing "ruby -S gem install ./pkg/hello_gem-0.1.0.gem":
ruby -S gem install ./pkg/hello_gem-0.1.0.gem
Successfully installed hello_gem-0.1.0
1 gem installed
Installing ri documentation for hello_gem-0.1.0...
Installing RDoc documentation for hello_gem-0.1.0...
Now you can push the gem to Github and Rubygems.org
First commit all the changes to Git
$ git add .
$ git commit -am "inital setup"
Second create an repository at github, and call it hello_gem
This will create a repository called hello_gem.git
Run the command
$ rake release
Committing hello_gem.gemspec
Pushing master to origin
Generated: hello_gem.gemspec
hello_gem.gemspec is valid.
Successfully built RubyGem
Name: hello_gem
Version: 0.1.0
File: hello_gem-0.1.0.gem
Executing "gem push ./pkg/hello_gem-0.1.0.gem":
gem push ./pkg/hello_gem-0.1.0.gem
Pushing gem to https://rubygems.org...
You do not have permission to push to this gem.
rake aborted!
Command failed with status (1): [gem push ./pkg/hello_gem-0.1.0.gem...]
- It generated the gemspec file
- validates the hello_gem.spec
- It pushes the gem to GIT
- ERROR: It fails to push the gem to rubygems.org
Gems are no longer hosted by Github, It has moved to Rubygems.org
- To move gems to Rubygems, use Gemcutter
- To install gemcutter
$ gem update --system
Now install the gem
$ gem install gemcutter
Now stay in the hello_gem folder, and build the gem
$ gem build hello_gem.gemspec
Successfully built RubyGem
Name: hello_gem
Version: 0.1.0
File: hello_gem-0.1.0.gem
Now push the gem to rubygems.org
$ gem push hello_gem-0.1.0.gem
Enter your Gemcutter credentials. Don't have an account yet? Create one at http://gemcutter.org/sign_up
Email: user@example.com
Password:
Signed in. Your api key has been stored in ~/.gemrc
Pushing gem to Gemcutter...
Successfully registered gem: hello_gem (0.1.0)
Now gem is part of the Rubygems.
To add Gemcutter support to Jeweler
In the Rakefile, enter the line
Jeweler::GemcutterTasks.new
- This line has to added after the require 'jeweler'
Now check if we have the gemcutter functionality in Jeweler
$ rake -T
rake gemcutter:release # Release gem to Gemcutter
Now execute the rake command to send the gem to rubygems.org
$ rake gemcutter:release
- This is exactly the same as 'gem push hello_gem-0.1.0.gem'
Now lets look at the current directory
$ tree
.
├── Gemfile
├── Gemfile.lock
├── hello_gem.gemspec
├── lib
│ └── hello_gem.rb
├── LICENSE.txt
├── pkg
│ └── hello_gem-0.1.0.gem
├── Rakefile
├── README.rdoc
├── spec
│ ├── hello_gem_spec.rb
│ └── spec_helper.rb
└── VERSION
3 directories, 11 files
So far the gem is empty so lets write something to it.
Let start writing to it, in the lib/hello_gem.rb
$ cat lib/hello_gem.rb
class HelloGem
def self.hi
puts "Hello World!"
end
end
Now bump the version to a minor release
$ rake version:bump:minor
Current version: 0.1.0
Updated version: 0.2.0
Update the gem in ur local machine
$ rake install
Successfully built RubyGem
Name: hello_gem
Version: 0.2.0
File: hello_gem-0.2.0.gem
Executing "ruby -S gem install ./pkg/hello_gem-0.2.0.gem":
ruby -S gem install ./pkg/hello_gem-0.2.0.gem
Successfully installed hello_gem-0.2.0
1 gem installed
Installing ri documentation for hello_gem-0.2.0...
Installing RDoc documentation for hello_gem-0.2.0...
Check if the gem is updated.
$ irb
ruby-1.9.2-p290 :001 > require 'hello_gem'
=> true
ruby-1.9.2-p290 :002 > HelloGem.hi
Hello World!
=> nil
Modify the gem file to require another file.
- create a directory in the lib with the same name 'hello_gem'
$ mkdir lib/hello_gem
- create a file called translator.rb and write the following
$ cat lib/hello_gem/translator.rb
class Translator
def initialize(language)
@language = language
end
def hi
case @language
when 'spanish'
"Hola Mundo!"
when 'english'
"Hello World!"
else
"ERROR !!!"
end
end
end
- Modify the gemfile to include this translator
$ cat lib/hello_gem.rb
require 'hello_gem/translator'
class HelloGem
def self.hi(language = 'english')
translator = Translator.new(language)
translator.hi
end
end
Now update the git repository
$ git add .
$ git commit -am "hello_gem/translator added"
$ rake version:bump:minor
$ rake install
$ irb
> require 'hello_gem'
=> true
> HelloGem.hi
=> "Hello World!"
> HelloGem.hi('english')
=> "Hello World!"
> HelloGem.hi('spanish')
=> "Hola Mundo!"
> HelloGem.hi('hindi')
=> "ERROR !!!"
To make the executable
$ mkdir bin
$ touch bin/hello_gem
$ chmod a+x bin/hello_gem
Edit the bin/hello_gem
$ cat bin/hello_gem
#!/usr/bin/env ruby
require 'hello_gem'
puts HelloGem.hi(ARGV[0])
To make this executable, we have include the following line in the gemspec
$ cat hello_gem.gemspec
Gem::Specification.new do |s|
:
s.executables << 'hello_gem'
end
Update the git repository and reinstall the gem
On the command line
$ hello_gem english
Hello World!
$ hello_gem spanish
Hola Mundo!
Testing, In the spec folder, edit hello_gem_spec.rb
$ cat spec/hello_gem_spec.rb
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
describe "HelloGem" do
it "should return Hello World" do
HelloGem.hi.should == 'Hello World!'
end
it "should return Hello World" do
HelloGem.hi('english').should == 'Hello World!'
end
it "should return Hola mundo" do
HelloGem.hi('spanish').should == 'Hola Mundo!'
end
it "should return error" do
HelloGem.hi('french').should == 'ERROR !!!'
end
end
Execute the tests to make sure it passes
$ rspec spec/
....
Finished in 0.0005 seconds
4 examples, 0 failures
Documentation of work.
In the hello_gem.rb
$ cat lib/hello_gem.rb
# The main HelloGem class
class HelloGem
# Say Hi to the world.
#
# Example:
# >> HelloGem.hi('spanish')
# => Hola Mundo!
#
# Arguments:
# language: (string)
def self.hi(language = 'english')
:
Resouces:
http://guides.rubygems.org/make-your-own-gem/
http://asciicasts.com/episodes/183-gemcutter-jeweler