Jake Scruggs

writes ruby/wears crazy shirts

Mar 31, 2007

My Commute

Working in downtown Chicago has its advantages -- everyday includes a scenic walk along the Chicago River:




And after a hard day of delivering business value, who doesn't enjoy a movie and a nice drink?

When I first started working with Rails, I had a windows laptop and so that’s where I worked. Later I got on two different Rails projects that used OSX (on Mac minis). Now I’m using Kubuntu. I thought I’d take a minute to compare them all.

I’m not going to mince words here -- try to avoid developing in Windows if at all possible for these reasons:

  • Tests will run very slow (by a factor of 10 or more).
  • The mysql drivers are not so good (When I developed in windows, I noticed I kept losing my connection to the database during operations that took more than a second or two and I couldn’t get any of the replacement drivers to work).
  • A fair amount of the plugins will be much harder to install (we are using the Raspell gem for “did you mean” functionality which needs aspell and the windows dudes still haven’t figured out how to install it. On Ubuntu, it was a simple “aptitude install”).
  • Help online is usually not geared towards the Rails on Windows developer.
  • If you have to develop in Windows, get IntelliJ and load up Cygwin

If money is no object go for a Mac:

  • TextMate is about as good as it gets for Rails Development (It has a bunch of readily available macros and pretty darn good auto completion).
  • All the cool kids use Macs for development so there’s plenty of help online.
  • They’re very pretty and fun to use (this sounds like a lame reason but if you're going to be using something for 8 hours a day it might as well bring you some joy).
  • However, sometimes the package management on the Mac let me down. Fink and Ports and all that tend to fight it out and getting image magic installed ended up taking down the whole system (we had to wipe it -- no foolin’).

If you think Mac’s are overpriced, then go with Ubuntu (or some other linux distro).

  • It’s free!
  • It has a rockin’ package management system.
  • IntelliJ (with the Ruby plugin) is pretty darn good and I have a feeling its going to get better.

Really the choice between OSX and Linux is mostly the choice between TextMate and IntelliJ (or Eclipse/RadRails). And, for now, I think TextMate has a slight edge. TextMate’s auto complete is a joy to work with while IntelliJ’s indexing makes for crazy fast searching. In fact once IntelliJ gets a bit better (don’t let me down Jet Brains – help a brother out with some autocomplete (and maybe some refactoring support)) then it’s just a choice between a really slick operating system and merely a functional one.

So I use RSpec's built in mocking framework for my mocking/stubbing and it works quite well. I sent up a mock like so:


mock_active_record_instance =
mock("give it a name here, but probably a better one than this")

and put some expectations on it like so:

mock_active_record_instance.should_receive(:id).and_return(1)

but some calls to the mock I don't care about so I can stub them out like so:

mock_active_record_instance.stub!(:name).
and_return("Arthur, King of the Britons")

If I don't need it to return anything I can leave off the and_return and it will return nil. But it's tedious to do that. Lately I tend to use OpenStructs as my mocks like so:

mock_active_record_instance = OpenStruct.new
mock_active_record_instance.should_receive(:id).and_return(1)

Now here's what's cool about that: My spec(test) will fail if the expectation of a call to id isn't met, but any other calls will be ignored (and nil returned). If I had made mock_active_record_instance a mock, like in the first example, I'd have to mock or stub out all the calls it's going to get and that is just painful. This way I can ignore the stuff I don't want to spec(test) painlessly.

You can also do fun stuff like so:

mock_active_record_instance = OpenStruct.new(:height => "5'10''",
:weight => 260,
:cars => ["hyundai", "saturn"])


So now mock_active_record_instance.cars will return an array with 2 stings. And height will return "5'10''" and weight will return 260. Maybe, in the future, a call to weight will return a smaller number -- I'm working on it.

Warning -- it may be that you have to do this because too many things are going on in the method you are specifying(testing). A better solution might be to figure out how to shorten up that method.

Jay Fields wrote about using OpenStructs in a series of blog posts about stubbing in rails which are totally worth reading.

Since Rails partials can see all the @variables of their parent view it’s pretty common to see partials with @’s all over the place. But the cool thing about partials is reusing them in other views and if you do you have to remember to populate all the stuff it needs and name everything the way it wants. Bah, I say. More and more I find myself explicitly calling partials with locals even if seems a bit redundant:


<%= render(:partial => 'content/poll',
:locals => {:poll => @poll}) %>

It goes along with this "partials are like methods" analogy I’ve been thinking about lately. And in big complicated pages with lots ‘o partials everything seems more clear. What do you think?

In my previous post I whined about not knowing how to mock/stub partials and helper methods in RSpec view specs. Now I have the answer and I’d like to thank the RSpec users mailing list and David Chelimsky for taking my phone call.

In short, it’s all about @controller.template


@controller.template.stub!(:a_helper_method).and_return(true)

Stubs out the appropriately named a_helper_method and returns true. You can mock it out also like so:

@controller.template.should_receive(:a_helper_method).
at_least(:once).and_return(true)

Which is like the stub except that it checks to see that a_helper_method was called at least once

For partials you do this:

@controller.template.should_receive(:render).
with(:partial => 'form', :locals => {:cookie => mock_cookie})

Which checks to make sure the partial _form.rhtml is rendered and that the view attempted to pass mock_cookie in as a local. Since I didn’t specify a return it will return nil and I don’t have to worry about what’s in the _form view (of course, I’ll spec it by itself). Cool.

There’s just one problem: You can’t mock/stub a partial inside a partial. Let’s say that inside _form is another partial and while I was specifying _form I wanted to mock it out like so:

@controller.template.should_receive(:render).
with(:partial => 'piece_of_form')

But later in the spec when I do this:

render :partial => ‘form’

I’m making a call to the template to render and it gets intercepted by the mocking framework! So not only do I get an error that the wrong thing was rendered (_form instead of _piece_of_form) but I’ve intercepted the call so I don’t get inside the view at all. Even if I were to expect the call to render _form I make inside the spec (which is weird) I wouldn’t be able to render the _form. Bummer.

Oh well, I got almost all of what I wanted.

I got an email today from a friend asking me about specifying views in RSpec in which he admitted he hadn’t done it much and first reaction was “I know what you mean!” Because it’s hard to spec views when you’re not hitting the database. You have to mock or stub out so many calls to your object just to get at the one or two lines you want to spec. And then I realized why I hate specifying views so much: It’s exactly like specifying a huge method. There’s all this stuff going on and you only care about one little bit and so you end up with 10 lines of mocking/stubbing to get to 3 lines of what you really want to say. Now with a ginormous method I have the option of pulling out little pieces of functionality into smaller methods and going straight at them. Then I can stub out those smaller methods when I’m specifying the big one. I can do this a little by creating a bunch of partials and specifying them individually, but when I want to spec the parent of all those partials I need to be able to stub them out. But I can’t figure out how to do that. The same goes for helper methods. I spec those individually already so I don’t want to spec them again but I can’t figure out how to stub them out. If I could do these two things I think specifying views would be much less painful.

Off to the internet for answers!

A few days ago I blogged about solving a sticky problem by overwriting the “new” method on an ActiveRecord object inside a test (spec). Something I should have mentioned is that this is dangerous because if another spec (test) tries to call new and gets executed after the dangerous spec/test is run, then of course it won’t have the original new method. And it’s a very hard error to track down unless you know it’s been redefined. The solution to this, should you need to do it (and you probably won’t – any good mocking framework will probably do what you want), is to wrap a context around all the contexts that need it and use context_setup like this:


context 'When the situation demands it' do
context_setup do
Class SomeObject
def some_method_to_overwrite
#do whatever I want -- Bwaa ha ha!
end
end
end

context 'Some context' do
#specs go here
end

context 'Some other context' do
#more specs go here
end
end

After it drops out of the context, the method isn’t redefined anymore. Yeah! Of course, to be real good and safe you should probably alias the new method in the setup and reassign it back in the teardown. But this works too.

I loves me some RSpec, but I’ve had this consistent problem on my last two projects when RSpec and Rcov are run together: Sometimes you get Seg Faults. In a previous post I talked about my solution to this (redefining the new method on ActiveRecord objects), but it was a hacky solution and I’m glad to say that it’s out of the code base as of today. On a hunch this weekend I installed RSpec 0.8.2 (we had been using 0.7.5.1), took out my super-fun hacktacular solution from a spec and it ran fine.

But why?

Looking through RSpec’s list of bugs fixed I didn’t see any reference to the bug I logged a few months ago (I didn’t really expect too – they were never able to reproduce it) but I do have any idea. David Chelimsky (lead dev of RSpec) had been telling me for awhile about how he was going to change RSpec to stop using method_missing on object because when Rails takes it for its own purposes, then RSpec has to some hacky things to steal it back (David wrote about it in "rspec.should use_a_little_less_magic"and so did I in "Battle of the method_missings"). Since the removal of that code was the big change between 0.7.5.1 and 0.8.2, I’m gonna guess that it was the problem.

Persistent, baffling problem?

Windows: restart computer
Linux: change file permissions

I need to Tattoo this on the back of my hand so I can see it while I type.

Long day.

So if you’ve heard about Ruby, you’ve probably heard about method_missing (short summary: if an object receives a message it doesn’t understand it calls method_missing which you can overwrite. This allows Rails ActiveRecord to handle User.find_by_email_and_name_and_phone_number on the fly -- it parses the message and gives you the method you want dynamically). But when too many things try to use it at once you get some interesting problems. At some point RSpec enabled calling object_instance.should_include('thing') by using method_missing on Object to catch any message that started with should_. So, in the previous example, RSpec would look for a method called include? on the object_instance, pass 'thing' into that, and tell you about it if it failed. Which is pretty cool because instead of saying:


assert_equal ['a', 'b', 'c'], object_instance.some_method

you could say:

object_instance.should_eql ['a', 'b', 'c']

which is more in line with ruby’s quest for code that looks like natural language.

But, when you use RSpec with Rails the method_missings fight. RSpec overrides method_missing and then Rails steals it back and you get all sorts of bugs. Sure you can do some kinda ugly stuff to steal it back again, but then the Rails source changes and you have another bug to chase. So with the release of Rspec 0.8 there is a new syntax supported and the old way has been deprecated (the maintainers of Rspec promise that they will provide a conversion script before they take the old syntax out of the framework). So

object_instance.should_include('thing')

becomes:

object_instance.should include('thing')

Why? Because now RSpec just has to add a 'should' method to the Object class which takes in an operator. No method missing on Object at all, so Rails can do all the fanciness it wants.

There are two implications here. One, if you’re writing a ruby framework you should be careful about method_missing as your users may want it too. And two, if you’re thinking about adding method_missing to an object that inherits from a Rails object, beware.