Post on 15-Jan-2015
description
Josh Nichols technicalpickles.com
RubyGems and You
Josh Nichols technicalpickles.com
• How ‘require’ works
• Where rubygems fits in
• Creating your own rubygem from scratch
• Creating your own rubygem using jeweler
Overview
Josh Nichols technicalpickles.com
•How ‘require’ works
• Where rubygems fits in
• Creating your own rubygem from scratch
• Creating your own rubygem using jeweler
Overview
Josh Nichols technicalpickles.com
executes the contents of a file
require
Josh Nichols technicalpickles.com
# foo.rbputs "zomg, so awesome"
# bar.rbrequire 'foo.rb'
$ ruby bar.rbzomg, so awesome
Josh Nichols technicalpickles.com
absolute path
require ‘/usr/lib/awesome.rb’
Josh Nichols technicalpickles.com
relative path
require ‘subdir/foo.rb’
Josh Nichols technicalpickles.com
can omit the .rb
require ‘subdir/foo’
Josh Nichols technicalpickles.com
list of directories to look for required files
$LOAD_PATH
Josh Nichols technicalpickles.com
$LOAD_PATH includes your ruby install....this actually lives under a path like:
/usr/local/lib/ruby/1.8/
require ‘net/http’
Josh Nichols technicalpickles.com
only will execute a particular path once
require
Josh Nichols technicalpickles.com
# foo.rbputs "zomg, so awesome"
# bar.rbrequire 'foo'require 'foo'require './foo'
$ ruby bar.rbzomg, so awesomezomg, so awesome
Josh Nichols technicalpickles.com
• Different environments (mac vs. win. vs. linux)
• People install stuff to random places
• Different versions of libraries
• What do we do?
Dealing with diversity...
Josh Nichols technicalpickles.com
MASS HYSTERIA!
Josh Nichols technicalpickles.com
• How ‘require’ works
•Where rubygems fits in
• Creating your own rubygem from scratch
• Creating your own rubygem using jeweler
Overview
Josh Nichols technicalpickles.com
• Handles downloading and installing library
• Manages $LOAD_PATH
• Allows a developer to package & distribute their library
Enter RubyGems
Josh Nichols technicalpickles.com
• gem install burninator
Installing
Josh Nichols technicalpickles.com
Using gems
require 'rubygems'require 'burninator'
Josh Nichols technicalpickles.com
Using gems in under Rails
# config/environment.rb, or anywhere reallyrequire 'burninator'
Josh Nichols technicalpickles.com
Using gems in under Rails
# config/environment.rbconfig.gem 'burninator'
Josh Nichols technicalpickles.com
Using gems in under Rails
# create vendor/gems...# then 'gem unpack' gems there# config/environment.rbRails::Initializer.run do |config| config.load_paths += Dir["#{RAILS_ROOT}/vendor/gems/**"].map do |dir| File.directory?(lib = "#{dir}/lib") ? lib : dir endend
Josh Nichols technicalpickles.com
Where do gems live?
Josh Nichols technicalpickles.com
• RubyGems already knows about it by default
• Has been the defacto standard for hosting
Josh Nichols technicalpickles.com
• But you need to apply for projects...
• And you need extra tools to publish gems...
Josh Nichols technicalpickles.com
• The new hotness
• Just create a repository and turn on RubyGem support
• Create a Gem::Specification, and push it
Josh Nichols technicalpickles.com
• How ‘require’ works
• Where rubygems fits in
•Creating your own rubygem from scratch
• Creating your own rubygem using jeweler
Overview
Josh Nichols technicalpickles.com
• Rake for automation
• Testing framework of choice (we’ll assume test/unit)
• RubyGems
Tools of the trade
Josh Nichols technicalpickles.com
Directory Layout
|~bin/| `-cylon_detector|~lib/| `-cylon_detector.rb|~test/| |-test_cylon_detector.rb| `-test_helper.rb|-LICENSE|-Rakefile`-README.rdoc
Josh Nichols technicalpickles.com
Rakefile basics
require 'rubygems'require 'rake'
Josh Nichols technicalpickles.com
• Metadata about your gem
• name, files, binaries, homepage, etc, etc
Gem::Specification
Josh Nichols technicalpickles.com
Rakefile gemspecspec = Gem::Specification.new do |s| s.name = 'cylon-detector' s.version = '0.8.1' s.authors = ['Josh Nichols'] s.date = '2009-02-03' s.email = 'josh@technicalpickles.com' s.files = FileList['{bin,lib}/**'] s.executables = 'cylon_detector' s.has_rdoc = true s.summary = 'Detect cylons with ease'end
Josh Nichols technicalpickles.com
Rakefile gemspec
task :gemspec do File.open('cylon-detector.gemspec', 'w') do |file| file.write spec.to_ruby endend
Josh Nichols technicalpickles.com
Rakefile package
require 'rake/gempackagetask'Rake::GemPackageTask.new(spec) do |pkg| pkg.need_zip = false pkg.need_tar = falseend
Josh Nichols technicalpickles.com
Rakefile rdoc
require 'rake/rdoctask'Rake::RDocTask.new do |rdoc| rdoc.rdoc_dir = 'rdoc' rdoc.title = 'cylon-detector' rdoc.options << '--line-numbers' << '--inline-source' rdoc.rdoc_files.include('README.rdoc') rdoc.rdoc_files.include('lib/**/*.rb')end
Josh Nichols technicalpickles.com
Rakefile test
require 'rake/testtask'Rake::TestTask.new(:test) do |t| t.test_files = 'test/**/test_*.rb' t.verbose = falseend
Josh Nichols technicalpickles.com
Rakefile rcov
begin require 'rcov/rcovtask' Rcov::RcovTask.new do |t| t.test_files = 'test/**/test_*.rb' t.verbose = true endrescue LoadError task :rcov do abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov" endend
Josh Nichols technicalpickles.com
Rakefile default
task :default => :test
Josh Nichols technicalpickles.com
bin/cylon_detector
#!/usr/bin/env ruby
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))require 'cylon_detector'
# detection code here
Josh Nichols technicalpickles.com
• The entry point into your library
• Require all dependencies (internal and external)
• Design decisions
• generally want to namespace your project
• class or module?
• Do not require rubygems (unless you are interacting directly with it)
lib/cylon_detector.rb
Josh Nichols technicalpickles.com
• Central location to setup testing environment
test/test_helper.rb
require 'rubygems'require 'test/unit'
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))$LOAD_PATH.unshift(File.dirname(__FILE__))
require 'cylon_detector'
class Test::Unit::TestCaseend
Josh Nichols technicalpickles.com
test/test_cylon_detector.rb
require File.dirname(__FILE__) + '/test_helper'
class CylonDetectorTest < Test::Unit::TestCase # tests go hereend
Josh Nichols technicalpickles.com
• Hack and commit your code
• ‘rake gemspec’ and commit your gemspec
• push to GitHub
• wait for the gem to build
• rejoice and have some Scotch
Workflow
Josh Nichols technicalpickles.com
• How ‘require’ works
• Where rubygems fits in
• Creating your own rubygem from scratch
•Creating your own rubygem using jeweler
Overview
Josh Nichols technicalpickles.com
• Handles the grunt work
• Generator
• Skeleton project setup for your test framework of choice
• Starts a git repo setup for GitHub
• Creates the repo on GitHub and enables RubyGem for it
• Rake tasks
• Automate version bumping
• Releasing to GitHub, including tagging the release
Jeweler
Josh Nichols technicalpickles.com
• Choose between testing frameworks
• Test::Unit
• Shoulda
• RSpec
• Bacon
• Also includes cucumber stories enabled for
Generator
Josh Nichols technicalpickles.com
• Tracks current version in VERSION.yml
• Rake tasks for bumping the version
• version:bump:patch, version:bump:minor, version:bump:major
Versioning
Josh Nichols technicalpickles.com
patch versionAPI backward-compatible
bug fixesminor enhancements
0.8.5
Josh Nichols technicalpickles.com
minor versionmostly API backwards compatiblemore significant enhancements
0.8.5
Josh Nichols technicalpickles.com
major versionbreak API as much you wantusually signifies an overhaul
0.8.5
Josh Nichols technicalpickles.com
• Updates the gemspec based on the version
• Pushes to GitHub
• Tags the release with the version number
Releasing