Mark Needham

Thoughts on Software Development

Archive for the ‘Ruby’ tag

Ruby: Using a variable in a regex

with one comment

We’re using Web Mock on my current project to stub out some of the external web requests in some of our integration tests and I managed to get myself very confused while trying to use a variable inside a regular expression that I was trying to pass to the ‘stub_request’ method.

The code was roughly like this:

some_url = "http://service.com/method"
 
stub_request(:any, /some_url/).
        to_return(:body => File.new('/path/to/some.xml'),
                                      :headers => {'Content-Length' => 666, 'Content-Type' => 'text/xml'},
                  :status => 200,
                  :headers => {'Content-Type' => 'text/xml'})

The request was being stubbed when I hard coded the url inside the regular expression but not being stubbed when I used the variable like in the example above.

I somehow missed the blindingly obvious in hindsight solution of treating variables inside a regular expression as if they were being used in a string.

If we wrap the variable inside ‘#{}’ then our problem is solved:

some_url = "http://service.com/method"
 
stub_request(:any, /#{some_url}/).
        to_return(:body => File.new('/path/to/some.xml'),
                                      :headers => {'Content-Length' => 666, 'Content-Type' => 'text/xml'},
                  :status => 200,
                  :headers => {'Content-Type' => 'text/xml'})

I still can’t quite believe I didn’t spot it straight away.

Written by Mark Needham

October 27th, 2010 at 1:55 pm

Posted in Ruby

Tagged with

Ruby: Mocking or stubbing methods on the system under test

with 5 comments

An approach to testing which I haven’t seen before and am therefore assuming is more specific to Ruby is the idea of stubbing or mocking out functions on the system under test.

I’ve come across a couple of situations where this seems to be done:

  1. When stubbing out calls to methods which are being mixed into the class via a module
  2. When stubbing out calls to private methods within the class

I think the first approach is fine because typically we’ll have a direct test against that module’s methods elsewhere and it doesn’t make much sense to test the same thing again.

I initially liked the second approach as well because it simplifies the spec we’re writing.

For example if we have this code:

class FoosController : ApplicationController
   def index
      populate_something
   end
 
   private
 
   def populate_something
      @something = Something.find(...)    
   end
end

Then by stubbing out ‘populate_something’ we can write a spec like this:

describe FoosController do
   it "should populate something" do
      controller.stub(:populate_something) # and so on
 
      get :index
   end
end

Rather than:

describe FoosController do
   it "should populate something" do
      Something.stub(:find) # and so on
 
      get :index
   end
end

This is a fairly contrived example of course and the temptation to stub out a method on the system under test increases as the amount of dependencies and the complexity of them increases.

The problem we create for ourselves is that if we want to change the internal structure of our class, perhaps by inlining those private methods, then we’ll end up with specs failing even if the external behaviour remains exactly the same.

My current thinking is that if we get in a situation where we want to stub out something on the system under test then it’d probably be better to listen to that pain and try and work out a cleaner way of solving the problem.

Written by Mark Needham

October 24th, 2010 at 5:30 pm

Posted in Ruby

Tagged with

Ruby: Using alias with ‘indexers’

without comments

I’ve been browsing through some of the Rails routing code while following Jamis’ Buck’s blog post and I came across something I hadn’t seen before while inside the ‘NamedRouteCollection’ class.

The bit of code which initially confused me is in RouteSet.add_named_route:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
module ActionController
  module Routing
    class RouteSet
      def initialize
        ...
        self.named_routes = NamedRouteCollection.new
      end
 
      def add_named_route(name, path, options = {})
        # TODO - is options EVER used?
        name = options[:name_prefix] + name.to_s if options[:name_prefix]
        named_routes[name.to_sym] = add_route(path, options)
      end	
    end
  end
end

Reading the code on line 12 I was convinced that this code was being used to set a value into an array or hash so I was confused as to how the url/path helper methods which get added for named routes were being created since there didn’t seem to be any code which was calling the method in ‘NamedRouteCollection’ which would create them.

I eventually stumbled into the initializer code above which made me realise that ‘named_routes’ wasn’t actually a hash or array but an instance of ‘NamedRouteCollection’.

The methods ‘[]=’ and ‘[]‘ are aliases which call the ‘add’ and ‘get’ methods on ‘NamedRouteCollection’

module ActionController
  module Routing
    class RouteSet
      class NamedRouteCollection
        def add(name, route)
          routes[name.to_sym] = route
          define_named_route_methods(name, route) # creates the helper methods
        end
 
        def get(name)
          routes[name.to_sym]
        end
 
        alias []=   add
        alias []    get
      end
    end
  end
end

For me it seems like perhaps the creation of the helper methods could be the responsibility of another object although I can see why it’s been put in NamedRouteCollection since those helper methods are only created if you have a named route.

Either way it was pretty confusing for me initially that you could create this type of side effect from a method call that looked like it was just adding a key, value pair to an array.

Written by Mark Needham

October 18th, 2010 at 4:24 am

Posted in Ruby

Tagged with

Ruby: Hash default value

with 2 comments

I’ve been pairing a fair bit with Ashwin this week and one thing he showed me which I hadn’t previously seen is the ability to set a default value for a hash which gets returned if we search for a key that doesn’t exist.

This is an idea that I originally came across while playing around with Clojure but with Clojure the default value was defined in the calling code rather than in the hash definition.

For example:

(def scores {:mark 10 :dave 20})
 
(get scores :tony :0)

For a similar piece of code in Ruby we could write the following:

scores = { :mark => 10, :dave => 20 }
scores.default = 0

Now if we search for a key that doesn’t exist in the hash then we’ll get the value 0:

scores[:some_other_guy]
0

We’re using this in a couple of places in our code base already but it’ll be particularly useful for an upcoming piece of functionality where we want to vary the look and feel of some pages depending on certain criteria.

For the majority of users the look and feel will remain the same but for some of them it will vary slightly. Controlling that behaviour by using a hash with some default settings therefore seems like a reasonably good fit.

Written by Mark Needham

October 16th, 2010 at 2:02 pm

Posted in Ruby

Tagged with

Ruby: Active Record – Using ‘exclusive_scope’ in IRB

without comments

Ashwin and I have been working recently on a bit of code to make it possible to ‘soft delete’ some objects in our system.

We’re doing this by creating an additional column in that table called ‘deleted_at_date’ which we populate if a record is ‘deleted’.

As we wanted the rest of the application to ignore ‘deleted’ records we added a default scope to it:

class Foo < ActiveRecord::Base
   default_scope :conditions => "deleted_at_date is null"   
end

This works fine but we wanted to be able to see the status of all the records in IRB and with the default scope ‘Foo.all’ no longer returns ‘soft deleted’ records.

Luckily Active Record provides a protected method called ‘with_exclusive_scope‘ which we can use to get around this:

Foo.send(:with_exclusive_scope) { Foo.find(:all) }

Since it’s a protected method we can only access it in IRB by using ‘send’ which is a bit hacky, something David Heinemeier Hansson would refer to as syntactic vinegar.

Interestingly our first attempt to use ‘with_exclusive_scope’ involved writing the above code like this…

Foo.send(:with_exclusive_scope) { find(:all) }

..which results in the following error because when the closure was created ‘self’ referred to the main object rather than to ‘Foo’:

NoMethodError: undefined method `find' for #<Object:0xb77cd94c>
    from (irb):62
    from /var/lib/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2143:in `with_scope'
    from /var/lib/gems/1.8/gems/activerecord-2.3.5/lib/active_record/base.rb:2151:in `with_exclusive_scope'
    from (irb):62:in `send'
    from (irb):62
    from :0

Since the main object has no method called ‘find’ we get an exception thrown.

Written by Mark Needham

October 11th, 2010 at 7:03 pm

Posted in Ruby

Tagged with

Ruby: Getting the caller method with Kernel.caller

without comments

One of the things I’ve been finding when debugging Cucumber specs is that due to the number of levels of indirection present in those examples it becomes quite difficult to work out exactly how certain pieces of code got called.

In one cuke we were trying to work out how 4 objects of the same type were ending up in the database when it seemed like there should only be two.

Having failed to figure it out just by reading the code we resorted to putting calls to Kernel.caller inside the Factory Girl setup code so we could see how we’d ended up at that code:

p caller.inspect

It’s not a perfect solution – since the scenarios we write get parsed by Cucumber it’s hard to tell exactly which line the call stack started on – but it provided enough information for us to track down the steps which were calling the Factory Girl code in question.

Written by Mark Needham

October 8th, 2010 at 1:19 pm

Posted in Ruby

Tagged with

Rails: before_filter, rescue_from and so on

without comments

One thing I’ve noticed while browsing our Rails code base is that the first entry point inside a controller is much less frequently the method corresponding to the action than it would be with a C# ASP.NET MVC application.

The concept of filters exists in ASP.NET MVC but on the projects I’ve worked on they’ve been used significantly less than before filters would be in a Rails application.

As a result I’m getting much more in the habit of checking for the before filters in the ApplicationController when an action isn’t working as expected to try and figure out what’s going on.

One which caught us out the other day is the ‘rescue_from’ method which gets mixed in from Rescuable.

Every single time we tried to login we were just getting redirected back to the login page again with no exception being reported anywhere.

Eventually we realised that the InvalidAuthenticityToken exception was being thrown because we somehow had a different token stored in our browser’s cookie than was in the form.

Since our LoginController extends the ApplicationController, the following logic was being used to handle the exception:

class ApplicationController < ActionController::Base
   rescue_from ActionController::InvalidAuthenticityToken, :with => :redirect_to_referer
 
  def redirect_to_referer_or_path
    redirect_to request.referer
  end

We initially didn’t spot it because it was hidden away between a whole load of other before filters and includes of modules.

The convention as far as I can tell is to try and keep as little code as possible inside the action method and handle common logic – such as looking up a user based on an id or handling exceptions – in filters.

It helps to keep the code inside actions pretty clean and remove duplication but I just need to remember to check both the action and the top of the class for any filters when investigating problems.

Written by Mark Needham

October 5th, 2010 at 8:53 am

Posted in Ruby

Tagged with ,

RSpec: Another newbie mistake

with 3 comments

We recently had a spec which was checking that we didn’t receive a call to a specific method on an object…

describe "Our Object" do
	it "should not update property if user is not an admin" do
		our_user = Factory("user_with_role_x)
		User.stub!(:find).and_return(our_user)
 
		user.stub!(:is_admin?).and_return(false)
		user.should_not_receive(:property)
	end
end

…where ‘property’ refers to a field in the users table. In the code ‘property’ would get set like this:

class ObjectUnderTest
 
	def method_under_test
		user = User.find 4
 
		if user.is_admin?
			user.property = "random value"			
		end
	end

That test always passed but when we wrote the test to check that ‘property’ would be set if the user was an admin we found that it always failed.

The mistake is quite simple – the method that we wanted to check was received is actually called ‘property=’ rather than ‘property’!

Changing the spec to read like this solves the problem:

describe "Our Object" do
	it "should describe something" do
		our_user = Factory("user_with_role_x)
		User.stub!(:find).and_return(our_user)
 
		user.stub!(:is_admin?).and_return(false)
		user.should_not_receive(:property=)
	end
end

It didn’t take that long to figure it out but this is certainly a mistake you wouldn’t be able to make in a statically typed language.

Written by Mark Needham

September 30th, 2010 at 7:03 am

Posted in Ruby

Tagged with

Ruby: ActiveRecord 2.3.5 object equality

without comments

We learnt something interesting about the equality of ActiveRecord objects today while comparing two user objects – one which was being provided to our application by Warden and the other that we’d retrieved by a ‘User.find’ call.

Both objects referred to the same user in the database but were different instances in memory.

We needed to check that we were referring to the same user for one piece of functionality and were therefore able to make use of the ‘==’ method defined on ActiveRecord::Base which is defined in the documentation like so:

Public Instance methods
==(comparison_object)
Returns true if the comparison_object is the same object, or is of the same type and has the same id.

This worked fine but when trying to write a test around this code we found it quite difficult.

We wanted to simulate the fact that we had two objects in our application that referred to the same database entry but not the same object.

Our initial approach was something like this:

describe "ActiveRecord::Base Equality" do
	it "should let us have two objects which both point to the same user in the database" do
		# Create a user in the database with Factory Girl
		Factory(:user_with_x_role, :id => 15 )
 
		u = User.find 15
		u2 = User.find 15
 
		# the rest of our test where we'd insert u and u2 into the application
	end
end

Unfortunately when we ran the test we found that if we mutated ‘u’ in the production code then the value of ‘u2′ was also being mutated so they were somehow both referring to the same instance.

Our second attempt was to create a clone of the object so that they wouldn’t be referring to the same instance:

describe "ActiveRecord::Base Equality" do
	it "should let us have two objects which both point to the same user in the database" do
		# Create a user in the database with Factory Girl
		Factory(:user_with_x_role, :id => 15 )
 
		u = User.find 15
 
		u2 = u.clone
		u2.id = u.id
 
		# the rest of our test where we'd insert u and u2 into the application
	end
end

‘clone’ creates a copy of the object but removes the id. Since we want both our objects to have the same id so that they’ll be recognised as being equal we set the id on the next line.

Unfortunately we now found that the two objects weren’t being considered equal even though they were both of the same type and had the same id as per the documentation.

After a bit of binging with Google I came across an interesting post by fritz describing the code of ‘==’:

      # Returns true if the +comparison_object+ is the same object, or is of the same type and has the same id.
      def ==(comparison_object)
        comparison_object.equal?(self) ||
          (comparison_object.instance_of?(self.class) &&
            comparison_object.id == id &&
            !comparison_object.new_record?)
      end

In fact the ‘==’ code also takes into account whether or not the object passed to ‘==’ is new or not and since in our code we had ‘u == u2′ it would return false.

If we had ‘u2 == u’ then it would have passed!

Our current solution to the problem is to compare the ids of the objects in our code rather than the objects themselves but fritz also describes a way to monkey patch the ‘==’ method to make it a bit more useful.

Written by Mark Needham

September 30th, 2010 at 7:00 am

Posted in Ruby

Tagged with ,

Ruby: Intersection/Difference/Concatenation with collections

with one comment

We came across a couple of situations yesterday where we wanted to perform operations on two different arrays.

My immediate thought was that there should be some methods available similar to what we have in C# which Mike Wagg and I spoke about in our talk about using functional programming techniques in C#.

I was expecting to find methods with names indicating the operation they perform but in actual fact the methods are more like operators which makes for code that reads really well.

Intersection

This is useful when we have two collections and want to find the elements that exist in both of them.

In the world of C# we have an ‘Intersect’ method available as part of the LINQ library:

var collection1 = new int[] { 1,2,3,4 };
var collection2 = new int[] { 1,2,5,6 };
collection1.Intersect(collection2);

In Ruby we have the ‘&’ method:

ruby-1.8.7-p299 > [1,2,3,4]  & [1,2,5,6]
 => [1, 2]

Difference

This is useful when we have two collections and want to find items which are in one collection and not in the other.

In C# we can use the ‘Except’ method…

var collection1 = new int[] { 1,2,3,4 };
var collection2 = new int[] { 1,2 };
collection1.Except(collection2);

…whereas in Ruby we have the ‘-’ method:

ruby-1.8.7-p299 > [1,2,3,4]  - [1,2]
 => [3, 4]

Concatenation

This is useful when we have two collections and want to join the two collections together.

In C# we’d use the ‘Union’ method..

var collection1 = new int[] { 1,2,3 };
var collection2 = new int[] { 4,5,6 };
collection1.Union(collection2);

..and in Ruby we have the ‘+’ method:

ruby-1.8.7-p299 > [1,2,3]  + [4,5,6]
 => [1, 2, 3, 4, 5, 6]

These methods and others on array are well documented on ruby-doc.org

Written by Mark Needham

September 29th, 2010 at 3:28 am

Posted in Ruby

Tagged with