03
Feb

As a good little rspeccer, I try hard to write my specs to verify behaviour rather than any particular implementation of that behaviour, and, for the moment at least, I’m in the “isolate your controllers from the models” camp. If you’re not in that camp (i.e., you don’t mock and prefer to do functional testing alone), this post probably won’t interest you. One case I often had problems with was model instance creation. There are just so many darn ways to create a new model instance! For a few examples:

@order_item = OrderItem.new(:hi => "hem", :ho => "hum")
@order_item.save!

@order_item = order.order_items.create(:hi => "hem", :ho => "hum")

@order_item = OrderItem.some_custom_creation_method(:hi => "hem", :ho => "hum")

The Problem

When you’re writing your spec (up front, of course!), you don’t want to presume too much about how the implementation will unfold. So, do you stub the create method on the model class? But what if we implement using the new/save combo (as above)? Or, what if we create the model instance through an association?

My Solution

My first pass solution to this problem is the following, based on Matthew Heidemann’s association stubbing technique:

module Spec
  module Mocks
    module Methods
      def stub_creators!(association_name, klass, stubs = {}, valid = true)
        target_mock = Spec::Mocks::Mock.new(klass, {:save => valid, :valid? => valid}.merge!(stubs))
        target_mock.stub!(:save!).and_return do
          target_mock.save
          valid || raise(ActiveRecord::RecordNotSaved)
        end
        klass.stub!(:new).and_return(target_mock)
        klass.stub!(:create).and_return do
          target_mock.save
          target_mock
        end
        klass.stub!(:create!).and_return do
          target_mock.save!
          target_mock
        end
        mock_association = Spec::Mocks::Mock.new(association_name.to_s)
        mock_association.stub!(:create).and_return do
          target_mock.save
          target_mock
        end
        mock_association.stub!(:create!).and_return do
          target_mock.save!
          target_mock
        end
        mock_association.stub!(:build).and_return(target_mock)
        self.stub!(association_name).and_return(mock_association)
        target_mock
      end
    end
  end
end

What this is doing

The thinking here is that, when I write my spec, I don’t want to be concerned with whether the implementation takes the create, new/save, build/save, or other route. In my spec I just want to know that at some point the controller asked for a model instance to be created and saved. The above code, which I put in spec_helper.rb, allows my specs to do just that. Essentially, I stub save so that it returns true or false, depending upon the optional valid parameter, and the other creation stubs derive from that: save!, create, create! on the target association class and the association itself. I also stub out new and build for convenience. This code ensures that save is always called, even though we’ve stubbed out create etc. Now if I need to check that a controller action has caused a model instance to be created, I need only ever check that save is called.

An example

In my specs I call stub_creators! on an instance of the association owner (in our example, the association owner is Order), passing it the name of the association I want to stub (order_items), the model class of the association target (OrderItem), optional stubs for instances of the association target, and whether or not we want the returned model instance to be valid (defaults to true). With this in place, I can do this:

describe OrdersController do
  before(:each)
    @current_user = mock_model(User, :login => "me", :logged_in? => true)
    @order = @current_user.stub_creators!(:order_items, Order)
  end

  it "should create a new order_item" do
    @order.should_receive(:save).and_return(true)
    post 'create'
  end
end

And it doesn’t matter which route the implementation takes to create that model instance. As long as save is called at some point, I know the controller has triggered the creation of the instance somehow.

Thoughts

Now, while this seems to work for me, I don’t really know whether this is kosher. Is it a sensible approach to take? I haven’t tested this extensively; as I said, it’s a first pass. Also, there’s bound to be stuff missing from my solution (for example, it doesn’t handle find_or_create_by_). Can a similar approach be taken to the various ways to delete an object, too? I shall continue to experiment.

,


25
Jan

A quick search reveals that I’m not the only one who’s had difficulty installing the nokogiri Ruby gem on Mac OS X. The official docs recommend installing the fink or macports versions of libxml2, and so does this nokogiri tutorial over on the Engine Yard blog. I like macports. It’s a good way to stay up to date with the latest and greatest versions of everything, but I have this thing about trying to make things work with the libraries that come as standard on Mac OS X. I don’t know, maybe it’s that it reduces dependencies, or maybe I’m just strange.

Anyway, here’s how I got nokogiri to install under Snow Leopard without resorting to macports or fink:

sudo gem install nokogiri -- --with-xml2-include=/usr/include/libxml2 --with-xml2-lib=/usr/lib --with-xslt-dir=/usr

What’s weird is that, unless I’m mistaken, those paths are exactly where nokogiri should be looking for the relevant libxml2 files in the first place! I’m still to find out whether it all works as it’s supposed to. But installation is the first step! Let me know if it works for you.


06
Nov

Our daughter, Claire Elise, was born on October 29, 2009. Here’s a photo of her, and another with her proud family.

Claire Elise Robinson

Claire Elise Robinson

Big brother meets baby sister

Big brother meets baby sister



02
Oct

So I’ve been using Snow Leopard for a few weeks now. Not too many changes on the surface. The integration of ExposĂ© into the Dock is probably one of the more visible changes. But being in an organisation where Microsoft Exchange is the chosen communication and, dare I say it, collaboration platform, the Exchange support in Mail, iCal and Address Book is really useful.

However, there was one thing I couldn’t figure out how to do: booking a shared resource, such as a meeting room or a car park. Today, we figured out how to do it, and, in hindsight, it should have been obvious.

To book a shared resource, create a calendar event in iCal as you normally would, making sure the event is created in your Exchange calendar as opposed to your personal (local) one. Then, in the invitees field, add the resource you wish to book. Start typing the name of the resource, and if your Exchange integration is working correctly (and your IT people have set up the resources in Exchange correctly), it should find the resource just as if you were adding a person as an invitee. Once you’ve added the resource, you should see a link that says “Available meeting times…”. Click it. This will show you when the resource is available and when it’s booked, as well as the availability of any other people you’ve added to the invitees field. Once you’ve done that, you’re good to go! Microsoft Outlook users will see that the resource has been booked (if they’ve added the resource as a Shared Calendar to their Outlook console).

, ,


30
Aug

The Landing Pilot is the Non-Handling Pilot until the “decision altitude” call, when the Handling Non-Landing Pilot hands the handling to the Non-Handling Landing Pilot, unless the latter calls “go-around”, in which case the Handling Non-Landing Pilot, continues Handling and the Non-Handling Landing Pilot continues non-handling until the next call of “land” or “go-around”, as appropriate.

In view of the recent confusion over these rules, it was deemed necessary to restate them clearly.

– British Airways memorandum, quoted in Pilot Magazine, December 1996 (and in The Pragmatic Programmer, which is where I read it).

, , ,


24
Jul

As you probably know, I’m a ubicomp researcher by day. However, on the side, NICTA’s allowed me to allocate some of my time to develop a new way for researchers to review and publish papers. We’ve deployed a very early proof-of-concept of our idea called Citemine. We think Citemine has several nice properties, including a potentially more meaningful measure of research quality than existing indicators such as h index and raw citation counts. You can read all about the underlying mechanism in Citemine here. Until we deploy a feedback mechanism for papers, please leave your comments about Citemine at the official Citemine blog.

Note that we’re experiencing a few difficulties with our Citemine production server environment, which means slow page loads from time to time. And it’s clearly lacking polish, but hopefully it serves its purpose as a proof-of-concept so that you can get a feel for what it’s all about. But please do read the paper. I’ve been told it’s a fun read.

, , , , , , ,


26
Jun

A long time ago, in a Cooperative Research Centre far, far away (well, actually, it used to be just across the road from where I’m writing this post, but it sadly met its demise), a small group of researchers worked on a ubiquitous computing project that came to be known as PACE: Pervasive Autonomic Context-aware Environments. This group produced a framework for context-aware computing, which was the subject of many research papers at Pervasive, PerCom, JPMC and elsewhere. For various reasons, the source code for PACE has only just now come out into the open. Yes, you can now download the PACE framework from SourceForge. Unfortunately, there won’t be a lot of support offered along with the code.

, ,


12
Apr

Queensland Rail will be offering south-east Queensland commuters free wireless access to the internet from early 2010, according to the Minister for Transport, Rachel Nolan. This access will use spare capacity on the infrastructure used to transmit real-time video footage from surveillance cameras to QR’s control room at Central Station.

One thing from that story that caught my attention was this:

She (Rachel Nolan) said people living near train lines or stations would not be able to tap into the free internet service because it would be “firewalled”.

That would have to be one pretty intelligent firewall! Here are some actual possibilities to guard against free-loaders. One not so attractive way to do it would be to set a limit on daily downloads. The theory is that there’s only so much you could download on the longest possible trip on the QR network in south-east Queensland (say, Gold Coast to Nambour, or something like that). The other more attractive solution, in my opinion, would be to tie usage to go cards. Your internet session starts when you swipe on at the beginning of your journey, and it finishes when you swipe off. There’d be some kind of web-based login procedure like you get at hotels and elsewhere, where you enter your go card number to gain access; or regular users could have the option of registering the MAC address of their wireless card with QR/Translink to skip the login procedure. Given that it still takes ages for a credit card top up to find its way onto my go card, I don’t hold out much hope for QR/Translink being able to implement this particular solution within the already very optimistic time frame of early 2010. But I do think it’s a reasonable long term solution. It might even help Translink in their quest to move more commuters over to the go card from paper tickets.

, , , ,


10
Apr

There are many ways to measure brand awareness. As in most analyses, you shouldn’t rely on any single metric to determine which brands have most mindshare. Having said that, the Social Radar Top 50 Social Brands ranking is interesting. It measures conversations and web chatter. According to the ranking, Twitter comes out on top. Google comes in second, and Facebook makes it into fifth place. One of Twitter’s major competitors, FriendFeed, doesn’t even make it into the top 50 by this particular measure (did Scoble back the wrong horse and Kawasaki the right one?). But this ranking didn’t just include “social networking” brands. Rather, it was a survey of how frequently any brand was mentioned in a collection of blog posts, news feeds, forums, social networks and Twitter posts. Interestingly, such well known brands as Coke and McDonald’s fell outside the top 50. I imagine this is because these brands no longer have novelty value. They are ingrained in our culture. Really the only time we could be bothered blogging about these sorts of brands is when controversy strikes, or when someone makes a provocative movie like Super Size Me.

So what does this mean? It means that right now Twitter is hot. People are talking about it, and that’s the best that Biz Stone and company could hope for. The big question for Twitter is how to convert all the talk into more users, and ultimately revenue. If they do manage to do this, it would be nice to know how they did it!

, , ,


22
Mar

Heard this song on the radio a while ago and couldn’t track it down. But today I caught it on ABC Local Radio, would you believe.

,