Ruby makes Rails, Javascript makes Ajax, Dr Nic makes Magic
Generating new gems for graceful goodliness
You don't share code. I know, I know, you've had good reasons - you don't know how to create a Ruby gem, how to upload it to a gem server like RubyForge, and you're a chicken. Today we'll remove the first of these minor roadblocks, with a New Gem Generator!
Now you can take any library or Rails plugin or command line application, gemify it, and easily share it with the Ruby world. With gems you get in-built version support (you can specify which version of a gem you want when you use it via the require_gem method), an encapsulated, consistent folder structure for your bin/lib/test folders, and you get cross-platform support for bin apps. Too much niftiness to ignore, really.
The New Gem Generator is like the rails
command for rails applications, but it creates the folders and starting files for a new gem. It's called newgem
.
Tutorial
Aim
To convert the Map by Method (previously called Map by Pluralisation) library into a gem.
See original and demo articles. Sex on a stick - soon to be gemified before your very eyes. (Download instructions for the prebuilt gem)
Installation
> gem install newgem
Download from rubyforge if you have firewall problems (as I do at work) and need to get the gem explicitly first. THEN run the above command in the folder you saved the gem.
Create new gem
> newgem map_by_method
creating: map_by_method
creating: map_by_method/CHANGELOG
creating: map_by_method/README
creating: map_by_method/lib
creating: map_by_method/lib/map_by_method
creating: map_by_method/lib/map_by_method.rb
creating: map_by_method/lib/map_by_method/version.rb
creating: map_by_method/Rakefile
creating: map_by_method/test
creating: map_by_method/test/all_tests.rb
creating: map_by_method/test/test_helper.rb
creating: map_by_method/test/map_by_method_test.rb
creating: map_by_method/examples
creating: map_by_method/bin
Copy in the library
The generated lib/map_by_method.rb
file looks like:
Dir['map_by_method/**/*.rb'].sort.each { |lib| require lib }
This will automatically include (require
), in alphabetical order, the files in the
lib/map_by_method
folder. If you need the files required in a specific order, then do it explicitly here, for example:
require 'foo'
require 'bar'
require 'tar'
or
%w(foo bar tar).each {|lib| require lib}
For this gem there won't be any additional library files, so we'll just copy in the following code into the lib/map_by_method.rb
file and remove the library loading code.
module MapByMethod
def self.included(base)
super
base.module_eval <<-EOS
def method_missing(method, *args, &block)
super
rescue NoMethodError
error = $!
begin
re = /(map|collect|select|each|reject)_([¥¥w¥¥_]+¥¥??)/
if (match = method.to_s.match(re))
iterator, callmethod = match[1..2]
return self.send(iterator) {|item| item.send callmethod}
end
return self.map {|item| item.send method.to_s.singularize.to_sym}
rescue NoMethodError
nil
end
raise error
end
EOS
end
end
unless String.instance_methods.include? "singularize"
class String
def singularize
self.gsub(/e?s¥Z/,'')
end
end
end
Array.send :include, MapByMethod
Package your gem into a .gem file
From the root folder of your gem run rake package
:
> rake package
(in C:/InstantRails/ruby_apps/map_by_method)
rm -r .config
Successfully built RubyGem
Name: map_by_method
Version: 0.0.1
File: map_by_method-0.0.1.gem
mv map_by_method-0.0.1.gem pkg/map_by_method-0.0.1.gem
Tada! You are the owner of a gem.
Install your gem onto your machine
Your Ruby (and Rails) applications can only use the gemified libraries once you have installed the packaged gem. This is the same for other people who will use your gem.
Typically you install a gem from a remote gem server such as rubyforge. Today, you will install the gem locally:
> gem install pkg/map_by_method-0.0.1.gem
Attempting local installation of 'pkg/map_by_method-0.0.1.gem'
Successfully installed map_by_method, version 0.0.1
Installing RDoc documentation for map_by_method-0.0.1…
Note that it created and installed RDoc documentation for the library too. Each user automatically has a copy of the generated documentation for your libraries (if you actually added documentation to your code).
Unit testing
Look in the test
folder and see that it has created a map_by_method_test.rb
unit test file to get you started. Put tests in there. Add more test files. Run rake test
from the project's root folder and watch all your tests succeed or fail. Be good.
Version numbers
Note that the generated gem is map_by_method-0.0.1.gem
. The 0.0.1 is the version number of the gem, and you can easily change this as you wish as you gem takes on new features and fixes.
There are two common version number formats:
X.Y.Z - X = major release number, Y = minor release number, Z = patch/bug fix number
or
X.Y.Z.svn = svn is the subversion number at the time the gem was released.
The latter is the default implementation generated by newgem. If you want the simpler version number format (the 1st one), then remove the following line from your Rakefile (around line 13):
REV = File.read(".svn/entries")[/committed-rev="(¥d+)"/, 1] rescue nil
Your gem has a prebuilt mechanism for specifying the X.Y.Z portion of the version number.
Go to lib/map_by_method/version.rb
module MapByMethod #:nodoc:
module VERSION #:nodoc:
MAJOR = 0
MINOR = 0
TINY = 1
STRING = [MAJOR, MINOR, TINY].join('.')
end
end
Change MINOR and TINY to:
MINOR = 1
TINY = 0
And repackage and reinstall your gem:
> rake package
(in C:/InstantRails/ruby_apps/map_by_method)
rm -r .config
Successfully built RubyGem
Name: map_by_method
Version: 0.1.0
File: map_by_method-0.1.0.gem
mv map_by_method-0.1.0.gem pkg/map_by_method-0.1.0.gem
> gem install pkg/map_by_method-0.1.0.gem
Attempting local installation of 'pkg/map_by_method-0.1.0.gem'
Successfully installed map_by_method, version 0.1.0
Installing RDoc documentation for map_by_method-0.1.0…
And you're done. Next you would upload your gem to a gem server such as RubyForge, or one your company runs internally to share gems via the "gem install" mechanism.
map_by_method already on RubyForge
If you want the map_by_method gem, its already on RubyForge, so you can remotely install it:
gem install map_by_method
0 Comments