ar_mailer 1.5.0
Eric Hodel | Fri, 16 Oct 2009 00:02:05 GMT
ar_mailer is a two-phase delivery agent for ActionMailer. Even delivering 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.
Changes
- Added --pid-file option. See --help for details.
- Minor improvements to --help, argument error output
dnssd 1.3.1
Eric Hodel | Wed, 14 Oct 2009 03:05:58 GMT
dnssd version 1.3.1 has been released!
DNS Service Discovery (aka Bonjour, MDNS) API for Ruby. Implements browsing, resolving, registration and domain enumeration. Supports avahi's DNSSD compatibility layer for avahi 0.6.25 or newer.
Changes
- 1 bug fix
- Fix regexp for parsing the fullname. Patch by James Sadler.
imap_to_rss 1.1
Eric Hodel | Tue, 01 Sep 2009 22:47:00 GMT
imap_to_rss version 1.1 has been released!
IMAPToRSS turns messages on an IMAP server into RSS entries when the match a handler. Included handlers work for email from Amazon, HSBC and UPS. IMAPToRSS automatically loads handlers for any other mail.
Changes:
- 1 major enhancement
- Added iTunes handler
- 1 bug fix
- Fixed various bugs in the Amazon handler
dnssd 1.3
Eric Hodel | Wed, 19 Aug 2009 04:31:00 GMT
DNS Service Discovery (aka Bonjour, MDNS) API for Ruby. Implements browsing, resolving, registration and domain enumeration. Supports avahi’s DNSSD compatibility layer for avahi 0.6.25 or newer.
Changes
- 4 major enhancements
- Added DNSSD::Service.get_property
- Added DNSSD::Service#getaddrinfo
- Added DNSSD::Service#add_record
- Added DNSSD::Service#query_record
- 5 minor enhancements
- DNSSD::Reply#connect now uses DNSSD::Service#getaddrinfo (faster)
- DNSSD::Service#register behaves properly when blockless
- Broke up DNSSD::Reply into specific subclasses
- Added sample/query_record.rb
- sample/*.rb work with each other now for clarity of implementation
- 2 bug fixes
- Fix hierarchical domains like \.mac\.name.members.mac.com.
- Fix compilation against avahi 0.6.25
On Ruby C Extensions
Eric Hodel | Tue, 18 Aug 2009 02:07:40 GMT
I’m not a great C coder, but I have implemented, cleaned up and read a few C extensions for Ruby and I’ve got some tips for writing C extensions
C is Bad
The C itself is your biggest enemy when writing C extensions. The more you write the harder it is for you to maintain and the harder it will be for anyone else to improve or fix your code in the future. The closer your C extension code is to the library’s API the better you can use Ruby to glue all the pieces together into a friendly interface.
Ruby is Good
With less C code and more Ruby code you end up a library that’s easier to refactor, adapt and extend. Generic data manipulation, simple math, convenience functions, etc. are all easier to write, test and debug when written in Ruby. There’s no need to recompile between changes, worry about compiler warnings, or fix type errors.
If you’re returning results from an operation, do as much of the work in Ruby as possible. If there are objects that can be created in Ruby create them in Ruby. If you get a struct sockaddr, unpack it on the Ruby side rather than calling the Socket methods from C using rb_funcall. If you’ve got an abstract representation of a flag bitfield, create the object on the Ruby side rather than calling rb_class_new_instance.
Check for what you need
mkmf.rb has loads of functions (dir_config, have_library, have_macro, have_func, have_type, have_struct_member, etc.) for determining whether or not you have everything you need to build your extension. When using these functions be sure to check the result and fail when what you need is missing.
Keep Up-to-date on the Ruby/C API
There’s tons of functions and macros for doing most of you need already built-in to Ruby. README.EXT has the overview, but there’s also ruby.h and intern.h which give you a list of functions you can use.
Use the friendly macros RSTRING_LEN, RSTRING_PTR and friends when playing with String, Array, etc. Use rb_define_alloc_func() with Data_Wrap_Struct(). Use RTEST and NIL_P for checking ruby results. Convert numbers with NUM2ULONG or NUM2INT, etc.
Play Nice with Threads
If you’re performing a blocking IO operation use rb_thread_wait_fd, rb_thread_fd_writable, etc. to keep other threads running. rb_thread_wait_for can be used for polling.
Don’t Repeat Yourself
While it is safe to repeatedly call rb_intern() if you have to invoke rb_funcall or rb_iv_set, it’s easier and prettier to use a static variable set from your Init function. Same for looking up classes using rb_path2class() or rb_define_class_under().
C is bad
It’s worth repeating. Writing C code is hard. Refactoring C code is hard. Debugging C code is hard. Do as little as possible in C and you’ll thank yourself down the road.
dnssd 1.2
Eric Hodel | Thu, 13 Aug 2009 05:45:00 GMT
DNS Service Discovery (aka Bonjour, MDNS) API for Ruby. Implements browsing, resolving, registration and domain enumeration.
Changes:
- 4 major enhancements
- DNSSD::Service is now directly instantiable
- DNSSD.announce which registers a server socket you’ve created
- DNSSD::Reply.connect which connects to a browsed service
- Fix asynchronous service shutdown crash
- 8 minor enhancements
- DNSSD.resolve now optionally accepts a DNSSD::Reply from DNSSD.browse
- Use rb_thread_wait_fd instead of custom rb_thread_select code
- DNSSD::Reply#protocol and DNSSD::Reply#service_name
- Added missing error classes
- Added missing InterfaceUnicast constant
- Improved Documentation
- Use C constants in ext/dnssd/errors.c
- Reduced C code in ext/dnssd/service.c for greater control. See DNSSD::Service
- 4 bug fixes
- Don’t invoke block on callback if none was provided
- Remove ext/dnssd/dns_sd.h so the correct header is used
- DNSSD::NoMemoryError is now raised instead of NoMemError
- DNSSD::ReferenceUsedError is now correctly named DNSSD::RefusedError
vi bindings for irb on OS X
Eric Hodel | Tue, 11 Aug 2009 20:56:22 GMT
OS X uses editline(3) instead of readline(3) so ~/.inputrc doesn’t do anything for irb or other tools using readline via the editline wrapper.
Instead, use ~/.editrc:
bind -v
bind \\t rl_complete
Which gives you vi bindings in irb.
Update
Now with tab completion thanks to Curt Sampson from an ancient netbsd-users email!
Converting from REXML to Nokogiri
Eric Hodel | Thu, 18 Jun 2009 01:02:02 GMT
Nokogiri is pretty darn cool, certainly far cooler than REXML. I switched UPnP to Nokogiri, and here’s a handy guide.
require 'rexml/document'
Becomes
require 'nokogiri'
REXML::Document.new
Becomes
Nokogiri::XML
Both accept String or IO objects
my_element.element['element/path']
Becomes
my_element.at 'element > path'
You can use CSS in #at
my_element.each_element 'element/path' do |sub_element|
Becomes
my_element.xpath('./xmlns:element/xmlns:path').each do |sub_element|
”.” is used to select sub-elements of this one
See also Nokogiri’s Node documentation.
UPnP 1.2.0
Eric Hodel | Wed, 17 Jun 2009 00:06:07 GMT
An implementation of the UPnP protocol
Changes
- 2 minor enhancements
- Workaround for missing socket constants on Windows. Reported by Yuri.
- upnp_discover now shows action argument and return value names.
- 4 bug fixes
- Method name must not include entire URI. Reported by Ian Macdonald.
- Step in allowedValueRange is optional. Reported by Ian Macdonald.
- upnp_listen works with all notification types. Reported by Ian Macdonald.
- upnp_discover now warns when a device failed to instantiate. Reported by Ian Macdonald.
A Project Naming Recommendation
Eric Hodel | Wed, 20 May 2009 23:08:02 GMT
I’ve gone through many different styles of project names, but I think I’ve finally found a naming scheme I like.
In the past, I’ve used class names with uppercase letters, dashed names and underscored names, and I think the underscores are the best for projects I’m packaging in ruby.
Rails solidified the convention of mapping CamelCase class names to underscored file names (class IMAPProcesor is defined in imap_processor.rb). Using underscored gem names makes it easy for people to figure out what file to require (same as the project name) or what class name to look for in ri.
If I have a plugin gem or an extension I’ll tack on the sub-project’s name with a dash. If I wanted to add a new handler for imap_to_rss for Chase bank email, the gem would be named imap_to_rss-chase.
This makes it easy to find in gem list -p and it conveniently namespaces the extension. It also would look nice with gems from github which break up author and project with a dash (drbrain-imap_to_rss-chase, if I used github). As an added bonus, when double-clicking any underscored part OS X only highlights a part of the name making cut-and-paste a little more convenient for picking apart gem names.
Currently almost 95% of gem names start with lowercase letters, 6% contain uppercase letters anywhere in the name, a little over 20% use dashes, 16% use underscore. Sixteen use both underscores and dashes (my favorite name being what_does_this_error_mean-merb).

Articles