RubyGems Beta 0.9.0.8
Eric Hodel | Tue, 26 Dec 2006 10:17:48 GMT
Beta version 0.9.0.8 is now available with:
gem update --system --source http://onestepback.org/betagems
Merry christmas from the RubyGems project!
If you find any bugs, report them on the RubyGems bug tracker.
Upgrade note
While require_gem was deprecated in 0.9.0, the bin stubs are still using it (oops!). To get rid of the warnings printed by rake or other bin stubs simply reinstall the gem. In the next beta ‘gem pristine—all’ will fix all your gem bin stubs.
What’s new since 0.9.0?
Lots! Many changes both big and small! Here’s an incomplete summary:
- require_gem is deprecated and will print a warning. Use gem instead.
- RubyGems now requires ruby 1.8.2 or greater.
- gem command changes
- new gem pristine command
- new gem outdated command
- new gem sources command
- gem uninstall can uninstall multiple gems
- gem install uses the cache instead of downloading
- gem install returns non-zero exit code on failure
- gem install can now set shebang on bin stubs (env or ruby)
- gem help output now fits in 80 columns
- now -w clean
- many proxy installation improvements
- gem cert impromevents
- RubyGems is now easier to use as a library.
- Easier programatic installs
- Easier inspection of local and remote gems
- extension building enhancements
- error reporting enhancements (less odd exceptions)
- many bugs fixed or closed (0 bugs in tracker!)
- require now loads .jar files
- select bug fixes:
- installing from scratch fixed
- gem install—force forces
- installing from read-only location works
- gem uninstall requires full name
- gem install obeys GEM_HOME for bin scripts
- RubyGems now installs on ruby 1.9
For full details, read the ChangeLog.
Onward Hoe!
Eric Hodel | Sat, 28 Oct 2006 05:15:57 GMT
I used Hoe to release the paginator files… and I have to say that’s the easiest, least painful release I’ve ever done. As Ryan said at the conference, it makes it easy to release often—and that is spectacular!
As a self-described Rake nerd, I find Hoe to be truly compelling from a technical standpoint—but its possible effect on the community is even more exciting. Quicker, smaller releases are better for everyone, and with the addition of sow to the library, getting up and running is easier than ever.
My thanks to Ryan Davis and Ara Howard (not to mention the bevy of other contributers) for making something like this available to the community.
RingyDingy 1.1.0 Released
Eric Hodel | Tue, 24 Oct 2006 15:59:00 GMT
RingyDingy version 1.1.0 has been released!
http://seattlerb.rubyforge.org/RingyDingy
RingyDingy automatically re-registers your DRb service with a RingServer should communication with the RingServer stop.
Changes:
- Added ring_server executable (Rinda::RingServer wrapper)
- Daemon mode
- Rinda::RingServer service listingph
- Remote verbose mode enable-disable
- Switched to Hoe
RingyDingy-1.0.0
Eric Hodel | Sat, 09 Sep 2006 23:29:00 GMT
RingyDingy is a little boat that keeps your DRb service afloat!
RingyDingy automatically registers a service with a RingServer. If communication between the RingServer and the RingyDingy is lost, RingyDingy will re-register its service with the RingServer when it reappears.
Similarly, the RingServer will automatically drop registrations by a RingyDingy that it can't communicate with after a short timeout.
Installing RingyDingy
Just install the gem: gem install RingyDingy
Using RingyDingy
You'll need a Rinda::RingServer, you can download one here.
Once you've got that running you can have a service register itself:
require 'rubygems'
require 'ringy_dingy'
require 'my_drb_service'
my_drb_service = MyDRbService.new
RingyDingy.new(my_drb_service).run
DRb.thread.join
Full documentation is available from ri once you've installed the gem.
To learn more about Rinda::RingServer, you can read my handy tutorial How to use Ruby's Rinda::Ring.
mem_inspect and png
Eric Hodel | Thu, 31 Aug 2006 22:52:00 GMT
I'm pleased to announce to new libraries written by members of the Seattle Ruby Brigade, mem_inspect and png!
mem_inspect
mem_inspect is ObjectSpace.each_object on crack. mem_inspect gives you the contents of each slot in Ruby's heap. mem_inspect also includes viewers that let you visualize the contents of Ruby's heap.
To install:
sudo gem install mem_inspect
Then you'll need to build a patched ruby:
ruby_mem_inspect_build
You'll then have a ruby capable of running mem_inspect in mem_inspect_ruby_1_8.
You can make an image with:
mem_inspect_ruby_1_8/ruby_mem_inspect -S ruby_mem_dump
Which will give you a PNG in your current directory named: mem_inspect.PID.TIMESTAMP.png
You'll get an image that looks something like this:
http://flickr.com/photos/drbrain/229482312/
Bigger:
http://flickr.com/photo_zoom.gne?id=229482312&size=o
To dump a PDF any time you want:
require 'meminspect/png_viewer'
MemInspect::PNGViewer.new(1024, 768).draw
You can also dump to an AquaTerm plot window if you have RubyCocoa and AquaTerm installed.
require 'meminspect/aquaterm_viewer'
MemInspect::AquatermViewer.new(1024, 768).draw
png
png is a pure-ruby PNG writing library written by Ryan Davis.
To install:
sudo gem install png
To use:
require 'png'
canvas = PNG::Canvas.new 200, 200
# Set a point to a color
canvas[100, 100] = PNG::Color::Black
# draw an anti-aliased line
canvas.line 50, 50, 100, 50, PNG::Color::Blue
png = PNG.new canvas
png.save 'blah.png'
Subclassing vs include
Eric Hodel | Wed, 23 Aug 2006 18:15:00 GMT
In memcached Basics for Rails Rob Sanheim asked:[W]hy make the cached model a class to extend instead of a module? Whether or not a model is cached should be an implementation detail, and shouldn’t define the hierarchy for a class. I know I would rather not use the power of (single!) inheritance just to cache something, when a mix-in should be plenty powerful to do it.
The short answer is:
Using a class the correct way to overlay features on top of another class.
Here’s my long answer:
When you use a class you get super, and super is a beautiful thing. It automatically walks your class’ ancestors and calls the right method in the right order.
A module doesn’t have this property so you can’t use it to overlay features on top of a class. The class’ implementation will always be called before the module’s implementation.
Now you’re going to say something about using alias to shuffle methods around. You could do that, but you’ll have to do this for each method you want to overlay (five in CachedModel) which involves lots of extra typing “do_the_thingy_without_the_stuff” that you could have had for free (and more-prettily) with “super”.
You also get another problem that may cause subtle bugs. When you use alias to overlay features the order of execution is dependent upon the order the files are required in! Intentionally writing code where the behavior may change file load order gives me the heebie-jeebies.
Having to do all that work to get the benefits of a subclass tells me that a module isn’t powerful enough to do what a subclass can, so a module isn’t the right way to add a cache.
I avoid* using modules to overlay features of a class, but do use them to add orthogonal or complementary features. Typically when I write a module it ends up being used like Comparable, Enumerable or Singleton. When I need to do something invasive a subclass is better.
Finally, making the argument that adding caching to ActiveRecord::Base via a subclass shouldn’t define the inheritance argument is very subjective. I could justify using a subclass by saying that ActiveRecord is a data storage class, and CachedModel is just another data store. If you want caching, inherit from CachedModel. If you don’t want caching, inherit from ActiveRecord::Base.
Except void or where prohibited by law. Your milage may vary. Break glass in case of emergency.
ar_mailer 1.1
Eric Hodel | Sat, 19 Aug 2006 22:41:15 GMT
ar_mailer allows you to queue ActionMailer emails in the database that will be sent with a separate process. ar_mailer gives drastic speed-ups when you need to send many emails.
To install ar_mailer: sudo gem install ar_mailer. You can also download ar_mailer from Rubyforge.
For instructions on how to convert from the regular delivery methods to using ar_mailer see the ar_mailer documentation.
ar_mailer-1.1.0 follows quick on the heels of ar_mailer 1.0. I’ve got several important features and bug fixes:
Features
- Added—chdir to set rails directory
- Added—environment to set RAILS_ENV
- Exits cleanly on TERM or INT signals
- Added FreeBSD rc.d script
- Exceptions during SMTP sending are now logged
- No longer waits if sending email took too long
Bugs fixed
- Fixed last send attempt in—mailq
- Better SMTP error handling
- Messages are removed from the queue on 5xx errors
- Added Net::SMTP.reset to avoid needing to recreate the connection
cached_model 1.2
Eric Hodel | Fri, 18 Aug 2006 07:38:00 GMT
Geoff writes about our cached_model and memcache-client libraries:
The Robot Co-Op has made a few libraries available. cached_model makes it easy to cache single row queries from ActiveRecord tables. memcache-client is a pure Ruby client and is included with the installation of cached_model.
—memcached Basics for Rails via Nuby on Rails
He even includes a useful how-to document to get you up and running!
(Yes, that's right, a brand new version of cached_model that works with Rails 1.1! If you've already downloaded 1.2.0, please upgrade to 1.2.1. I forgot that find_by_sql will return [], thanks to James Cox for pointing out my bug.)
ar_mailer
Eric Hodel | Tue, 15 Aug 2006 23:39:00 GMT
Rubyforge Project: http://rubyforge.org/projects/rctools
Documentation: http://dev.robotcoop.com/Tools/ar_mailer
About
Even deliviring email to the local machine may take too long when you have to send hundreds of messages. ar_mailer allows you to store messages into the database for later delivery by a separate process, ar_sendmail.
Installing ar_mailer
Just install the gem:
$ sudo gem install ar_mailer
Converting to ar_mailer
Go to your Rails project:
$ cd your_rails_projectCreate a new migration:
$ ar_sendmail --create-migrationYou'll need to redirect this into a file. If you want a different name provide the —table-name option. Create a new model:
$ ar_sendmail --create-modelYou'll need to redirect this into a file. If you want a different name provide the —table-name option. Change your email classes to inherit from ActionMailer::ARMailer instead of ActionMailer::Base:
--- app/model/emailer.rb.orig 2006-08-10 13:16:33.000000000 -0700 +++ app/model/emailer.rb 2006-08-10 13:16:43.000000000 -0700 @@ -1,4 +1,4 @@ -class Emailer < ActionMailer::Base +class Emailer < ActionMailer::ARMailer def comment_notification(comment) from comment.author.emailEdit config/environments/production.rb and set the delivery agent:
$ grep delivery_method config/environments/production.rb ActionMailer::Base.delivery_method = :activerecordRun ar_sendmail:
$ ar_sendmailYou can also run ar_sendmail from cron with -o, or as a daemon with -d. See ar_sendmail -h for full details.
Geocoding Goodness
Eric Hodel | Tue, 13 Jun 2006 22:01:00 GMT
I've implemented ruby bindings for the three major geocoding APIs as gems:
| API | gem name |
|---|---|
| Yahoo! | yahoo-geocode |
| google-geocode | |
| geocoder.us | geocoder-us |
And as a bonus, you get a Yahoo! search gem to search either the web or for locations, yahoo-search.
The bindings all have similar APIs, but return different objects depending upon what information the API reliably provides. Yahoo! gives the most information, followed by Google, followed by geocoder.us.
Yahoo!
require 'rubygems'
require 'yahoo/geocode'
yg = Yahoo::Geocode.new application_id
locations = yg.locate '701 First Street, Sunnyvale, CA'
p location.first.coordinates
(and searching for locations)
require 'rubygems'
require 'yahoo/local_search'
yls = Yahoo::LocalSearch.new application_id
results, = yls.locate 'pizza', 94306, 2
results.each do |location|
puts "#{location.title} at #{location.address}, #{location.city}"
end
require 'rubygems'
require 'google_geocode'
gg = GoogleGeocode.new application_id
location = gg.locate '1600 Amphitheater Pkwy, Mountain View, CA'
p location.coordinates
geocoder.us
documentationrequire 'rubygems'
require 'geocoder_us'
gu = GeocoderUs.new 'username', 'password'
p gu.locate('1924 E Denny Way, Seattle, WA')

Articles