Tuesday, May 6, 2008

Startup community in Baltimore

I just found about a very interesting Barcamp called SocialDevCamp East planned in Baltimore on Saturday, just a few miles south of my house. It's very heartening to see enthusiasm building for a tech community here on the east coast and this has gotten me thinking about the Baltimore startup community in general. Below are some notes on startup life in Baltimore.




  • Here are some Baltimore startups I know about:




    I'm sure there are more; send me some and I'll add them to the list.


  • I've talked to many other Baltimore entrepreneurs with ideas in various stages of development, and there are lots of hackers here working remotely (or commuting to DC and Northern Virginia) on startups. We're also the home of advertising.com which employs a lot of smart people and brings a lot of talent to the area.


  • I meet a lot of cool hackers through the local Ruby on Rails meetup.


  • One of my favorite blogs is written by a Baltimorean, Paul Barry. He's a Ruby on Rails expert, but has in no way drunk the Kool Aid. He's got plenty of love for Java and Scala and whatever else gets the job done.


  • I've been dreaming for awhile about organizing a "Baltimore Demo Night" where all of us could gather and show off our wares, get feedback, and so on. Who's down for that?

Advanced Rails Recipes out now

I contributed two recipes to the newly-released Advanced Rails Recipes which I highly recommend.  It's got 84 very eye-opening solutions to problems faced by a lot of Rails programmers.  

I feel lucky to be working with cool, open technology that's yielded an opportunity to be part of a project like this.

Thursday, May 1, 2008

Looking for Rails developers (who isn't?)

For the past seven months I've been building a cool new consumer web app with some folks in Austin, TX, otherinbox.com/, and we're looking for experienced Ruby On Rails developers. We're a small agile team led by Steven Smith, founder of FiveRuns.

The whole site is Rails-based and makes extensive use of Amazon Web Services (EC2, S3, and SQS) and there's a new awesome challenge every day. More info on our jobs page.

Sunday, March 23, 2008

Great explanation of Rails auto-loading

I thought Mark Bush did a great job of explaining Rails' auto-loading behavior on the Rails-talk mailing list.  I'm posting it here to help others find it, and so I remember where to find it next time I'm struggling with it.  I've known that Rails automatically requires and loads classes on the fly using standard conventions for module names -> file names, but I had a hard time grasping how it worked.  Mark explains it very concisely.

The Rails list has a low signal-to-noise ratio but it's still worth paying attention to for gems like this.

Saturday, March 15, 2008

Using stunnel to wrap Ruby network operations on the fly

In my current project, we need to be able to connect to POP3 servers. Some POP3 servers, such as Gmail, only allow SSL connections. Unfortunately, the Ruby 1.8.x net/pop library doesn't support SSL (although the 1.9 library does, but that was not an option for us in this project).

The usual answer here is to wrap your connection using stunnel, which acts as an SSL proxy for whatever traffic you want to send over it. Usually you run stunnel as a separate service pointing at the server, but since we'll be connecting to many different POP servers, I needed to be able to set up and tear down stunnels on the fly. The first attempt looked something like this:
system("echo -e 'foreground = yes\npid =\n[mail]\nclient = yes\n \
accept = 127.0.0.1:2000\nconnect = #{server}:#{port}\n' \
| stunnel -fd 0")
Since stunnel doesn't accept command-line options, you have to pipe options to it. The "fd -0" tells stunnel to read its configuration from file descriptor 0, better known as STDIN.

Since I need to run that command in a child process, then have the parent resume and make use of the child service, I embarked on a fun foray of Ruby's forking and threading capabilities.

First, I tried forking, replacing the child process with a call to exec instead of system, then detaching the parent and killing the child process when the POP session was done. This partially worked, but I couldn't figure out how to kill the child process, so I'd end up with multiple copies of stunnel running after the script ran, or the parent process itself would hang.

Looking through the Pickaxe chapter on threads and processes, I discovered IO.popen, which works perfectly. I can pipe input to STDIN, avoiding the ugliness of the "echo -e" above, and I can more easily kill the child process when I'm done.

This is what the final method looks like:
def stunnel_wrap(server, port)
stunnel = IO.popen("stunnel -fd 0",'w+')
stunnel.puts("foreground = yes\npid =\n[mail]\nclient = yes\n \
accept = 127.0.0.1:2000\nconnect = #{server}:#{port}\n"
)
stunnel.close_write
Kernel.sleep(1)
yield
ensure
Process.kill(9,stunnel.pid)
end
I handle exceptions at a higher layer in this class, so here all I do is make sure the stunnel process gets killed no matter what. I'm not sure if the sleep call is needed, but when I was testing this with Gmail it seemed to help to wait one second for the tunnel to activate before trying to use it.

To make the above example work, you just need to point your POP client at the stunnel (in this case 127.0.0.1 port 2000) and you'll be talking SSL to the server.
stunnel_wrap('pop.gmail.com',995) do
Net::POP3.start('127.0.0.1', 2000, account, password) do |pop|
# pop securely
end
end

Monday, February 18, 2008

ActiveRecord Double Validation Errors in RSpec

I had a strange error occur in one of my rspec model unit tests today, and I wanted to document it here because my solution (which is a bit of a hack) is the opposite of what worked for other people.

I have a bunch of tests that check to make sure I'm validating various properties of a model. All of a sudden, I started having tests fail because the validations seemed to be adding the same error twice.
'User creation should require domain names to be unique' FAILED
expected 1 error on :domain, got 2
This error only occured when my full suite of tests ran. If I ran the unit test by itself (or even if I just ran only the model tests by themselves), it didn't happen.  Unfortunately I didn't notice whatever it was I did to introduce this error, so I couldn't reverse it.

Several other people have encountered this problem, so I know it's because my tests are leaking state in some way.  Somehow I am doing something during my tests that rspec isn't able to clean up.  Usually it's because the tests are doing something weird with extra require or load statements, which causes multiple copies of the class to be loaded.  Removing these statements usually works.  

I had no such statements and so spent a while trying to sort this out.  On a whim, I added a require statement to the top of the failing User model spec, and that fixed it:
require 'user'
I wish I had more time to investigate, because it makes me thing I don't know enough about Rails autoloading behavior, or Ruby's loading behavior. 

If you're running into this same problem, I found these mailing lists threads to be useful:

Tuesday, February 12, 2008

Unobtrusive Firefox Plugin Click-to-Install

I've been working on a really cool new project, to be announced soon, where I've built a Rails-based web app that has two interfaces: one for humans to interact with inside of a browser, and a RESTful API for browser plugins to interact with via GETs and POSTs.  We want people to be able to interact with our site while visiting other sites.


I had seen other Firefox plugins that were click-to-install, but I had a hard time figuring out how to make it work for our plugin. Firefox users were having to "Save Link As.." and open the downloaded .xpi file manually.  Very old-fashioned.  So here's a quick note to help future Mozilla or Firefox developers who need to create a click-to-install plugin:


1) It's all done through Javascript, so anyone without Javascript will have to install your plugin the old-fashioned way.  The Mozilla site documents the API call you need to make.


2) I'm a huge proponent of unobtrusive javascript (UJS), which I learned by using Dan Webb's excellent LowPro framework. Thus I wanted to make sure that the click-to-install javascript was offered as a progressive enhancement to the normal HTML links we provided.  That way, everyone could have a link to the plugin file itself for manual installation, but people with Javascript could enjoy click-to-install.


In this part of the site, we weren't using any other Javascript libraries, so it seemed like overkill to include Prototype and LowPro just for this one effect.  So it was a great chance to learn how to roll my own UJS without library support.  I whipped up a quick UJS click-to-install technique following inspiration from this presentation.  Here's what I came up with:

<script defer="defer" type="text/javascript">
//<![CDATA[
function doXPITrigger() {
if (!document.getElementsByTagName) return false;
var links = document.getElementsByTagName("a");
for (var i=0; i < links.length; i++) {
if (links[i].className.match("firefox")) {
links[i].onclick = function() {
xpi={'Awesome New Project Toolbar':'/downloads/awesome_project.xpi'};
InstallTrigger.install(xpi);
return false;
}
}
}
}

window.onload = doXPITrigger
//]]>

3) I've seen other advice recommending you configure your web server to recognize the .xpi mimetype appropriately.  I did this but it didn't make much difference in my case.  Still, it's probably worth doing.  I added this line to our Apache config:


AddType application/x-xpinstall .xpi