Something to write about

December 26th, 2007

Greg Borenstein has put together a list of 50 blog posts he'd like to see in 2008. His theme that drives the list is "I know Ruby. Now what?" I see at least a couple in there that I could probably write a few useful sentences about, so maybe I'll have to give it a shot. What I really like about this list is that there are a number of ideas in there that could be written up in fairly short posts while still saying something worthwhile. Also, it covers a good deal of ground. There's more than a handful that I'd love to see written up, too. So get to it!

Here's a little tidbit that took me somewhat by surprise. I was poking around on my laptop trying to debug an issue with a Ruby library I'm trying to use. I ended up trying to find the man pages for the TCP socket API. Not the Ruby interface, but the native stack. The thing is, the Ruby TCPSocket class just wraps around the native implementation. But when I tried to find the man pages, they weren't there. I thought I had all the basic development packages installed, but apparently, there is a separate package for the development man pages. It turns out you need to do an 'apt-get install manpages-dev' to get them.

A quick twitter hack

October 19th, 2007

So, a friend of mine asked me to put together something that would update a particular twitter account every so often with content from a text file he sent me. Of course, anyone who has spent more than 30 seconds playing with twitter4r knows how simple this is, but I thought I'd post the code here just for posterity. It's not doing anything fancy whatsoever.

All it requires is a text file with the posts each on a separate line and a twitter.yml file that looks like this:

prod:
  login: user
  password: pass

I just went ahead and hard coded this to use prod as the environment since this is only a short-lived project. Anyway, here's the code, simple as it is:

#!/usr/bin/env ruby
require 'rubygems'
require 'twitter'
require 'twitter/console'

env = 'prod'
config_file = 'twitter.yml'

status = File.open('updates.txt') do |f|
  l = f.readlines
  l[rand(l.size)].chomp
end 

twitter = Twitter::Client.from_config(config_file, env)

twitter.status :post, status

Once again the Portland Ruby Brigade will be hosting an evening of wide ranging talks about Ruby. This year the focus is on people doing strange things with Ruby. Strange, of course, is anything just a bit outside the usual. If you've created a new Ruby-based interface for hacking your brand new internet-enabled phone (rPhone anyone?) or composed your latest bit of metaprogramming magic, we'd love to hear about it.

Rather than having a fixed list of presenters, we're keeping it open-ended and free form. We'll use the lightning talk inspired approach and give you each a 10 minute slot to tell us what you can cram in. Make it especially interesting and we might even give you an extra minute or two. Let us know (send email to tlockney+foscon@gmail.com) in advance if you are interested in presenting or show up early on the 24th to sign up for any remaining slots (we'll hold a few open until the event itself).

This will all be taking place on Tuesday, July 24th, 7:30PM at Holocene (http://www.holocene.org/) here in Portland, Oregon. This just happens to be the same week as O'Reilly's Open Source Convention and the final day of Ubuntu Live. So if you're in town for either of those or close enough to come join us anyway, you're more then welcome.

There will be plenty of Ruby fun going on and lots of socializing with other people interested in Ruby. Last year, FOSCON II was overflowing. We've found a new venue to fit you all in, so why would you miss it?

http://upcoming.yahoo.com/event/216872 or http://foscon2007.com

A while back I agreed to do tech reviews for two Ruby books from O’Reilly. The first of these, Ajax on Rails by Scott Raymond, was just published a few weeks ago. It looks to be quite an excellent piece of work (of course, I know the tech reviewing was top notch ;~). I just received word that the second, Rails Cookbook by Rob Orsini, has been published, too.

Both look to be worth picking up. I’ll be posting more about both soon, I hope.

RubyMesh lives!

November 19th, 2006

well, sorta anyway. I did some more playing around with why's modifications to mod_ruby and was able to throw together a quick test to show that in fact it should be quite possible to implement a SiteMesh-like system using Apache, mod_ruby (patched) and Hpricot. Here's, in short, how I did it.

First, I downloaded Apache 2.0.59 since that's close to the version we're running on the server on which I'll eventually be using this system (it's actually 2.0.55, but close enough, right?). Be sure to compile in the proxy module, since that's what we're trying to achieve here is filtering of reverse proxied content, like, say, a rails app.

Next, download this patched version of mod_ruby that includes support for filters. You'll want to make sure you build this against the Apache you just installed, so use the --with-apxs=... option (read the README.en file included in the tarball) to point to the correct apxs binary.

Once you've got everything installed, create a basic httpd.conf that looks something like this:

ServerRoot /opt/apache-mod-ruby
Listen 8080
LogLevel info

LoadModule rubymodule /opt/apache-mod-ruby/modules/modruby.so

RubyTimeOut 10
RubyAddPath /opt/apache-mod-ruby/rubylib
RubyRequire rubyMesh

ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/

<Proxy *>
  Order deny,allow
  Deny from all 
  Allow from 127.0.0.1
  RubyOutputFilter RubyMesh.instance REWRITER
  SetOutputFilter REWRITER
</Proxy>

Next, make sure you have the hpricot gem installed (gem install hpricot) and then create the file /opt/apache-mod-ruby/rubylib/rubyMesh.rb with the following content:

require 'singleton'
require 'rubygems'
require 'hpricot'

class RubyMesh
  include Singleton

  def output_filter(filter)
    if filter.req.content_type !~ %r!text\/html!
      filter.pass_on
    else
      doc = Hpricot(filter.read)
      (doc/"title").first.inner_html = "FooBar"
      filter.write doc.to_s
      filter.close
    end 
  end 
end

Oh, of course, you'll also need to have some app (in my case, a Rails app) running on port 3000. Load http://localhost:8080 in your browser and you should see that the title of has been changed to FooBar.

Next step is to figure out what I want the configuration of this thing to look like. Once that's planned out, I should be able to whip together a couple of classes and maybe even release my first gem. Of course, I'm not entirely sure how I like the idea of releasing a gem that's dependent on a hacked version of modruby, but... what are you going to do, eh? Maybe eventually a version of modruby that supports why's extensions will get released.

SiteMesh in Ruby?

November 9th, 2006

I've been working on setting up some servers for a project with which I'm involved (in all my infinite spare time). These servers are going to have a variety of web applications running (some of which will be third-party), but we (that is, me and the other guy ;~) would like to keep a somewhat consistent look & feel across the board.

Of course, the obvious solution is to just edit the templates provided with each application (assuming the have templates at all). As the number of applications grows, the enjoyment level of doing this decreases rapidly.

Another solution that was thrown around was to make sure all the applications output well-formed XHTML and use XSLT to churn the output into something we like. However, this involves a number of assumptions about the quality of the markup being generated by each application (not something we necessarily have control over) and requires installing a front end filtering system to process all the content before it's sent out over the interweb.

One approach which I've looked at in the past is to use something like SiteMesh which also does filtering, but is a bit more direct and doesn't require well-formed XHTML to do it's dirty work. On the other hand, it's a java-based system, and I'm hoping to avoid having to run a java application server for the foreseeable future (I know it's coming at some point, actually, but I'm going to limit that to just the servers that require it, if possible).

While chatting about this problem on the PDX.rb IRC channel a few weeks back, rcoder pointed me to this wonderful gem from why. I tried it out later that day and never could get it to work.

But tonight, I started fresh with a nice clean build of Apache and why's modified mod_ruby and I'm happy to report that I got his example working perfectly.

So now, the next step is to lay out a design for a SiteMesh like system, but using some nice Ruby idioms and conventions and see where I can get with this. If it gets to a point where it's halfway usable, I might just have something that I can put out for all to see. Of course, it will be a little weird releasing some code that depends on a hacked version of a little used (at least so far as I can tell) module for Apache, but that's the way things go sometimes.

Late last night while trying to get rails running on a server I was setting up, I ran into an odd error. Sadly, I failed to save the error message itself and my browser history has been woefully unhelpful in finding the google searches I did to track down the issue. However, I can recreate the sequence of steps I took to fix the problem.

First, though, let me give you the scenario. This box is running Ubuntu Dapper (6.06) but the scenario could apply to just about any Debian-based distro. I had been planning on running rails on top of the ruby .deb packages since I'll be eventually maintaining a potentially large number of boxes and installing from source is not so fun across a bunch of systems.

I did stumble on this patch for the issue, but it wasn't immediately obvious how straightforward it would be to patch the source and repackage it. I'm here to tell you, it turned out to be really damn easy. For more background info on the approach I took, you might want to read this article, but I'll outline the steps here for you if you don't want to skip over there first.

The first thing you will want to do is make sure you have the prerequisites for building packages. You can load them like so:

sudo apt-get install devscripts build-essential fakeroot

Next, you'll need to get the source for the package you want to patch:

sudo apt-get source ruby1.8

You will probably want to do this in a directory of it's own, since it can dump a number of files in your current directory depending upon the package you're updating.

After you've grabbed the source, you'll need to get any dependencies for this package:

sudo apt-get build-deps ruby1.8

At this point, you should have a directory called ruby1.8-1.8.4 in your current directory. Change into this directory.

You should see a directory under there called debian, in which will be another directory called patches. This is where we will add our patch file.

You'll notice that each patch file has a numeric prefix. You'll want to add a higher numbered patch than any of the existing files so that your patch gets applied last. To do so, I created a file called 904_extend32_fix.patch. The contents of this file were (based on the contents in the email linked above):

Index: pack.c
===================================================================
RCS file: /src/ruby/pack.c,v
retrieving revision 1.62.2.12
diff -u -w -b -p -r1.62.2.12 pack.c
--- ruby-1.8.4/pack.c   13 Oct 2005 14:30:49 -0000 1.62.2.12
+++ ruby-1.8.4/pack.c   16 Feb 2006 06:01:07 -0000
@@ -347,11 +347,11 @@ num2i32(x)
     return 0;                  /* not reached */
 }

-#if SIZEOF_LONG == SIZE32 || SIZEOF_INT == SIZE32
+#if SIZEOF_LONG == SIZE32
 # define EXTEND32(x) 
 #else
 /* invariant in modulo 1<<31 */
-# define EXTEND32(x) do {if (!natint) {(x) = (I32)(((1<<31)-1-(x))^~(~0<<31));}} while(0)
+# define EXTEND32(x) do { if (!natint) {(x) = (((1L<<31)-1-(x))^~(~0L<<31));}} while(0)
 #endif
 #if SIZEOF_SHORT == SIZE16
 # define EXTEND16(x)

At this point, you're just about done, all you need to do is run debuild -us -uc from that ruby1.8-1.8.4 directory. This will create a bunch of .deb files in the parent of this directory. At that stage, you're ready to install.

There are certainly some improvements to be made to this process. For one, I have yet to attempt to lock or hold the package, which means that next time there is an updated version of the package available, it will get updated without my patch. However, I'm not entirely sure whether that's going to be a problem. I'll do more research into it, but for now my problem is solved.

Another change to the approach that would improved things would be to edit the changelog that lives in that debian directory. Adding a new entry to the change log is both a good practice and tells the package build tools to update the version number of the package. However, that file is rather strictly formatted and there are special tools for editing it. I haven't investigate them, yet, so I won't discuss them any further here.

Rails Recipes

February 5th, 2006

A few days ago, Chad Fowler 's new book Rails Recipes was released in beta by the Pragmatic Programmers. As soon as I saw this, I printed out and read the excerpts they were making available. As I had hoped, they were great. Aside from a few typos (to be expected for a beta), the quality was excellent and I've already learned a few tricks. It was fun setting up mini-rails projects and quickly running through each recipe. I find examples are often the best way to learn things and this book is exactly the ticket.

Last night I went ahead and bought the beta PDF. I'm looking forward to reading the rest of it and watching it evolve through the beta process.

Sorry for those of you coming here expecting non-technical posts, but I did start this thing for technical purposes, after all, and I figured it was about time to return to form.

Tonight I was working on a little side project I'm doing. I needed to pull a bunch of legacy data into a new table for event data. To make this work, I created a set of models that referenced the old tables, using the syntax ActiveRecord provides to override it's default settings.

After figuring out how to make it work (I had to play with the database connection settings a bit), I decided to take a break and catch up on some blogs. Low and behold, I find that Dave Thomas went and described almost the exact same situation on his blog! I mean, even down to the "Legacy" prefix on his table names. And the reassuring bit is that he arrived at the same solution I did. Gotta love it.

More thoughts on Ruby on Rails
Once again, why (that's his name, not a typographic mistake -- then again, they might be one and the same) blows my head right off with a little bit of Ruby metaprogramming magic: .c( whytheluckystiff )o. -- Seeing Metaclasses Clearly
Darren Hobbs looks at Seaside and asks, "can your rails do this?" (More info on this Seaside functionality here.) To which I respond, why not? Of course, Rails doesn't use a component based approach (though it has been MUCH discussed ), but I don't see why it couldn't be extend to allow editing of the source. The only trick would be to figure out which files had been used in making up the current page. I wouldn't think this would be too hard. Either instrument Rails to annotate the session along the way with the layout, view, etc. used along the way of rendering the view or use introspection to figure out yourself (this would obviously be the less intrusive approach, but would also be subject to breakage if some of the core flow were to change). Of course, this image looks a good bit like a standard IDE class browsed, which brings to mind the idea of just pulling in all of your classes.

Rails Day 2005 - June 4th

April 15th, 2005

Rails Day 2005 - June 4th - seems to me this could be the right opportunity to get at least the basic functionality of Esperanticon off the ground. It would be at least some free publicity. On the other hand, I don't know how we'd get one piece done since it won't be able to use Rails. I need to talk to Justin about this. Sorry for the vagueness of this post, but I'm not sure we're ready to unleash this idea on the world yet. It might be too big for some of you to handle!

Rails Console

April 14th, 2005

One of the most underappreciated tools in the Rails toolshed is the console script. This script lets you interact with your model objects via the powerful irb (yeah, I know that's probably not the most definitive link for irb, but it's certainly the most fun). As quick and easy as it is to develop with Rails, console allows you to stop in the middle and double check that things are working the way you think they are.