Day Two at RailsConf

Posted by Eric Sat, 19 May 2007 03:09:00 GMT

Hello again from RailsConf. I’ve gone through five presentations. I don’t have any enormous revelations, and no good pictures yet, but I do have some observations. I’ll do this Larry King style.

…Uncle Bob and Jim Weirich are great public speakers. I’ve seen Uncle Bob do most of the CleanCode talk before, and I’ll go again at Agile 2007…Went for a run yesterday, Portland is quite pretty…Everyone I’ve met here has been unfailingly interesting, with nobody trying to ‘network’ just meet people like normal human beings…Spider Man 3 was mildly disappointing …If you get a chance to download the slides from Spam I Have Known, do so. Hugely entertaining…If you add videos to your presentation it’s fun, but not as much fun as genuine enthusiasm about your topic.

Okay I can’t do that for very long, how did Larry do it for 20 years? The highlights from today would have to be three things:

  • Keynote. The tone here is very different from your typical stuffy conference, and it’s great. Chad Fowler playing the ukulele, DHH referring to ‘unicorns’, I doubt you see these at a Windows Vista conference. Well you probably do, but it’s forced and trite. There’s a genuine enthusiasm here, because what we have here are 1600 developers who are all passionate craftsman who would do this for free. To any potential customers: That last part was a joke. We like to be paid. Speaking of paying, Dave Thomas gave a talk (which Gilberto attended) on Rails for charity, and that charity is still open at:

http://pragmaticstudio.com/dontate

Charity good, give some.

  • Clean Code. Uncle Bob is a “friend of the program” as they say in college and rather closely related to my boss, so my opinion is biased admittedly, but his speech today was packed and as always well received. If you want to see what he talked about hold the apple or ctrl key and click http://www.objectmentor.com. That will open the site in a new window, so you don’t go away.

  • Spam I have known. The presentations I saw the rest of the day were up/and/down. Nothing was bad exactly, and I know these people put a lot of effort into them so I won’t name names, but there wasn’t much memorable. I was beginning to think I’d have to make up something to blog today, until seeing Jim Weirich’s presentation on spam. Ruse has a really nice algorithm for detecting spam which has quite a few features but it centers around an idea so obvious you’ll wish you’d thought of it, the Tarpit. Spammers routinely defeat sites with one thing - feedback! They attack a site trying different things until they figure out why they were rejected. A Tarpit takes spam and doesn’t give them an error message, it puts it in the Tarpit. They think that their spam was successful, so they don’t change the spam. I think I’m going to grab it and try it for my personal wiki, which has never been replaced since I left the evils of corporate America.

Hello from RailsConf

Posted by Eric Thu, 17 May 2007 12:10:00 GMT

Of course if you’re reading this you’re probably at RailsConf so hello from here. I’m right next to you actually, to your right. Yep that’s me, hi. There’s a coffee stain on your shirt.

I plan to blog as much as possible from here, and hopefully bring a little of the experience back home to those of you that couldn’t make it. I just came out of my first tutorial, “your first day on JRuby on Rails”, and found it quite enjoyable. Admittedly we’ve been playing with JRuby for a little while know here at 8th Light, so much of it was stuff I already knew, but it was great to talk to Charles Nutter and get some of my questions answered directly. Some highlights:

  • Deployment with JRuby on Rails is a snap, assuming you’ve already got some sort of existing Java Enterprise setup. Using the GoldSpike plug-in creates a deployable WAR file. While I don’t see a reason for doing this on any current projects, for those of you out there using servers that might be resistant to setting up Apache/Mongrel this was a nice alternative. Install plug-in, run rake task and you have a deployable WAR file.

  • NetBeans for Ruby fairly stole the show. I’m a big TextMate fan, especially because I no longer debug with anything other than puts statements, so I don’t need a fully fledged IDE for Rails. That said the features they demonstrated for Ruby were great, including code completion, jumping to methods, and my personal favorite clicking a method call and jumping to it’s source code even if it was in a Gem. I’ve done a lot of hunting in Gems and this would be enormously helpful. Rudimentary refactoring support is expected as well, including support for rename method. I asked how this would work in Ruby and the plan is to show places where the rename could take place and leave the ultimate decision up to the user. I didn’t get to see this in action, and I’d like to because I fail to see how that is better than just using find. I’d be hard-pressed to switch from TextMate, I’m writing this post in it, but I could be convinced if NetBeans could be the “editor you live in.”

In other news the Portland Conference center is really nice, with pretty good wireless network connections. One thing I’d ask for would be more tables outside the ballrooms, as there are only about 6 and a lot of people have their Macs open on the floor. Speaking of which I’ve never been anywhere that the Mac so dominated. 80-90% of the people here are carrying MacBooks.

Now if you’ll excuse me, I’m hungry.

Test Driving Module Methods

Posted by Eric Thu, 03 May 2007 12:55:00 GMT

Recently I had the pleasure and frustration of working the net-sftp gem for Ruby. Pleasure because it’s a well written library, with an easy to use syntax that looks something like this:

Net::SFTP.start( 'localhost', :registry_options => { :logs => { :levels => { "sftp.*" => :debug } } }) do |sftp|
  sftp.put_file "test.data", "temp/blah.data"
  puts "getting remote file to local location..."
  sftp.get_file "temp/blah.data", "new.data"
end

The above is just a shortened version from one of the examples in the GEM itself. It’s simple to use and easy to read. Having written similar code in C++, for Windows no less, I can really appreciate how quickly this can get an FTP application off the ground. The frustration came when I went to test drive this guy. Net::SFTP.start is a module method, not a class member. I can’t stub it in the traditional way using the RSpec stub! command or use should_receive. On top of that it passes back a block, which needs to be tested to make sure it’s being called correctly. After a few shots at mocking it out Paul and I test drove it with an actual FTP server. In the short term that was necessary anyway, as a hazard of frequent mocking can be that you are only testing how well you read the API. You see that when the tests pass and the first shot at actually running the code blows up. In the long term the customer asked for a few new small features, changing directories and what not, and I really want to get this under long-term test to do that. So how do we do it?

Well we could stop using the .start command entirely. We could pass in a mock Net::SFTP object and test it, making sure to close it manually. Unfortunately that eliminates the clean code we see above, and if possible I’d like to keep it. The solution is to intercept the start method.

The first thing I do is monkey patch the code like so:

module Net ; module SFTP
  def start( *args, &block )
  end
  module_function :start
end ; end
context "My Context" do

I’ve put it before the context, to make sure it’s redefined before the object I’m testing is created. Next we need to expose our mock objects in the context to the monkey patch. This isn’t done with traditional writers and readers, because that would require finding the specific specification running for each time through the monkey patched start. Instead we make our mocks class members in the setup method, and create a class method in the context to retrieve the variables. The class method looks like this:

def Spec.get_mock_ftp_objects
  return @@mock_starter, @@mock_session
end

This reveals a bit of the underworkings of RSpec. Each block in the context block is turned into a class method using class_eval, as part of the Spec object. Making the method static allowed this new monkey patched method:

module Net
  module SFTP
    def start( *args, &block )
      @mock_starter, @mock_session = Spec.get_mock_ftp_objects
      @mock_starter.start args[0], args[1], args[2]
      yield @mock_session
    end
    module_function :start
  end
end

The code gets the two mock objects via our new method. Isn’t it grand how Ruby lets you return multiple objects? The call to start allows me to make sure that the arguments passed to the real start are correct. The real interesting call is the yield. By yielding the mock back to the object it will replace the sftp in the original code. Now I can test it! In fact I’ve already realized a bug in my code (in stopping) just by the process of doing this. I love it when a plan comes together. The final code example is here, I ended up extracting out a new class, so the names have changed. This one tests both the starting object and the block yielded:

require 'net/sftp'
require File.expand_path(File.dirname(__FILE__) + "/ftp_client")

module Net
  module SFTP
    def start( *args, &block )
      @mock_starter, @mock_session = Spec.get_mock_ftp_objects
      @mock_starter.start args[0], args[1], args[2]
      yield @mock_session
    end
    module_function :start
  end
end

context "FTP Client" do  
  setup do
    @client = FtpClient.new("test_server", "user", "password", "directory")
    @@mock_starter = mock('mock_starter')
    @@mock_session = mock('mock_session')
    @@mock_session.stub!(:opendir)
    @@mock_session.stub!(:close_handle)
  end

  specify "makes ftp connection, to proper place" do
    @@mock_starter.should_receive(:start).with("test_server", "user", "password")
    @client.read_from_server
  end

  specify "changes to ftp_directory, better close that handle" do
    @@mock_starter.should_receive(:start).with("test_server", "user", "password")
    @@mock_session.should_receive(:opendir).with("directory").and_return("fake handle")
    @@mock_session.should_receive(:close_handle).with("fake handle")
    @client.read_from_server
  end

  def Spec.get_mock_ftp_objects
    return @@mock_starter, @@mock_session
  end
end

Maybe this isn’t the best way to do this, but I like it. I’m looking forward to comments.

Older posts: 1 ... 4 5 6 7