Testing a rails before_filter method

I finally figured out a kind of cool way in Ruby using Rspec to test a controller’s before_filter method a few days ago.

While trying to figure this out, I came across all kinds of posts saying why you shouldn’t test the before_filter because it means looking too closely at the implementation by doing that.  (I disagree; I think this, like any other method, can and should be unit tested.)

I came across other posts that told how to skip the before_filter altogether and test everything else. (Valuable in some cases I’m sure, but not what I was trying to do.)

And I came across many other posts that had examples that did not work for me (perhaps different versions of rspec/ruby/rails or any number of things).

I came across some posts said to test the functionality of the before_filter method in one of the subclasses of ApplicationController.  I could do that, but then I have to pick a subclass at random.  And since the method I’m trying to test is defined ON ApplicationController, I feel like it is more intuitive to test that IN application_controller_spec.rb, not some other, random test.  And if the randomly chosen controller happened to ever get removed from the app in the future, the spec for that would also get removed, and thus inadvertently removing any coverage of the before_filter method in app controller.

I found out that Rspec has a cool way of defining anonymous controllers.  And this worked out well for testing ApplicationController.  So I wanted to share how I used anonymous controllers, as well as some things I tried along the way that did NOT work (almost, but not quite).

(These examples use Rails 3.1.1 and Rspec 2.12.0)

The application code:

application_controller.rb

# The before_filter method "check_permission" is defined here.  It is
# not specified as a before_filter in ApplicationController because
# some controllers in the app will want to use it, and some will not.
1  class ApplicationController
2    def check_permission
3      @current_user = session[:user]
4
5      #Check the permissions of the logged in user in the session
6      if @current_user does not have permission #pseudocode
7        render( :file => File.join(Rails.root, 'public/403.html'),
8                :status => 403,
9                :layout => false )
10     #else don’t do anything. The app will continue as usual
11   end
12 end

members_controller.rb

# There are rules around who can view members.
# Different logged in users can view different members.
1 class MembersController < ApplicationController
2   before_filter :check_permission
3
4   def show
5     member_id = params[:id]
6     # get the details for the given member id
7     # etc....
8   end
9 end

The test code:

I came across some suggestions that said to just write a test that calls the method directly.  But in this case, the before_filter method uses the HTTP session.  If you call a method outside of the context of an  HTTP get/post, you don’t have access to HTTP things like session, request or response.  So calling the method directly did not work:

application_controller_spec.rb

 1  require 'spec_helper'
 2
 3  describe ApplicationController do
 4    before do
 5      # Put a user in the session
 6      # do any other rspec mocking/stubbing necessary
 7    end
 8
 9    it 'should allow viewing of users if the user has permission' do
 10     ApplicationController.new.check_permission
 11     # then test stuff here ...
 12   end
 13 end

Running this gave the following error on the line 11.

RuntimeError:
 ActionController::Metal#session delegated to @_request.session, but @_request is nil: 
 #<ApplicationController:0x007fbac2aed3f8 @_routes=nil, @_action_has_layout=true, 
 @_view_context_class=nil, @_headers={"Content-Type"=>"text/html"}, @_status=200, 
 @_request=nil, @_response=nil>

I tried defining my own anonymous controller like this:

application_controller_spec.rb

 1  require 'spec_helper'
 2
 3  class AnonymousController < ApplicationController
 4    before_filter :check_permission
 5    def show
 6      render :text => 'Hello'
 7    end
 8  end
 9
 10 describe AnonymousController do
 11   before do
 12     # Put a user in the session
 13     # Any other rspec mocking/stubbing that needs done
 14   end
 15
 16   it 'should allow viewing of users if the user has permission' do
 17     get :show , :id => 123456
 18     response.code.should eq "200"
 19     response.body.should include "Hello"
 20   end
 21 end

And got this error on line 17:

ActionController::RoutingError:
 No route matches {:id=>"111111", :controller=>"anonymous", :action=>"show"}

But there’s a more Rspec-y way to do anonymous controllers.  And it magically sets up the routes for you to avoid the error above.

application_controller_spec.rb

 1  require 'spec_helper'
 2
 3  describe ApplicationController do
 4
 5    before do
 6      # put a user in the session
 7      # do any other rspec mocking/stubbing necessary
 8    end
 9
 10   # This is the anonymous controller:
 11   controller do
 12     before_filter :check_permission
 13
 14     def show
 15       render :text => "Hello"
 16     end
 17   end
 18
 19   it 'should allow viewing of users if the user has permission' do
 20     get :show , :id => 123456
 21     response.code.should eq "200"
 22     response.body.should include "Hello"
 23   end
 24
 25   it 'should not allow viewing of users if the user does not have permission' do
 26     get :show , :id => 111111
 27     response.code.should eq "403"
 28   end
 29 end
Posted in code. Tags: , . 2 Comments »

Model – View – Controller (MVC). Where do you put your business logic?

When I first started doing Rails development over a year ago, I often found other developers suggesting that I refactor my code to move the business logic out of the controller, and into the model.  After this happened several times, I wondered why this seemed so obvious to them, and why that wasn’t the way I was naturally doing things.  It wasn’t just me and another developer approaching problems in different ways.  It was multiple people approaching problems in a similar way — and then me.  I wondered why there was this general difference in thought processes and solutions?

I began to passively wonder if my background in Java was contributing in some way to my way of thinking here.  Since then, I have also heard other Rails developers who are working with former Java developers say things like

"these are good developers but they keep putting business logic in their controllers!"

That made me think more seriously about what a person’s Java background might have to do with this.

VIEW 

In earlier days of PHP, classic ASP, and early JSP, it was OK to put business logic in the view.  Back in the day, it was common to find <% %> tags in JSPs with all kinds of logic in the Java code.  I think we all now agree that business logic does not belong here. 

let the view deal only with DISPLAYING what it has.

MODEL 

It seems like I’ve spent a lot of time seeing a model as simply a data-holder class.  Something like a Struct in C.  Something like a Bean in Java, with private attributes, and with get/set methods for each attribute.  It’s just a data transfer object, nothing more.  But why?  Perhaps it comes from my EJB days.  That might explain why so many other former Java developers do the same thing.  To us,

the model carries data but is dumb. 

CONTROLLER 

I always thought of the controller as being the one smacking around the model objects to get them to do what the controller wants – and

what the controller wants the model to do, is the business logic. 

A RAILS WAY OF THINKING 

Give the model more credit.

The model isn’t so dumb after all.  It doesn’t just hold state.  It contains the business logic behind the behavior of that model.  A model knows better than any other code how itself behaves, what it does or does not do, and how it interacts with the outside world.  I can try to predict how my brother will behave in a given situation; I can take a guess based on what I know about him.  But only he knows for sure, and the only way I can know for sure is to interact directly with him and find out.

Let the controller control the flow of information.

This leaves the controller with only the responsibility of collecting information and routing it to the right place.  It’s the electronic curator that finds and obtains art, and hands it off to the decorators to display.  He decides what pieces go in which rooms.  However, the decorators (analogous to the view) are the ones that decide how to arrange the art within that room for all to see.

I still need to be reminded sometimes to not put so much logic in my controller.  It is starting to come more naturally to me, but old habits die hard I suppose.  This way of thinking makes more sense to me now that I understand where my past way of thinking comes from.  I like this new way because it really makes sense now, and also because

I find that code re-use comes much easier when needed business logic is already available in the model.

.

Posted in code. Tags: , . 7 Comments »

Ruby Sorting [2] – Common Mistakes When Sorting With Blocks


This sorting technique is one I’ve had a chance to use at work more lately. But what keeps tripping me up is when you use the block to sorting primarily by one field, with a secondary sort on another field. Let’s say Fish has species and type, and we have these fish in our database:

species type
Platy Sunset
Platy Calico
Molly Dalmation
Platy Rainbow
Guppy Fancy Tail
Platy Mickey Mouse

When I sort first by species, then by type, I keep accidentally doing the following, which gives the wrong sorted results:

>> fishes = Fish.find(:all) 

>> fishes.sort do |a,b|
?>   a.species <=> b.species
>>   a.type <=> b.type
>> end

Doing that, I end up with a list like:

species type
Platy Calico
Molly Dalmation
Guppy Fancy Tail
Platy Mickey Mouse
Platy Rainbow
Platy Sunset

It ignores my first sort on species, and ends up sorting only by type!

Why? What’s wrong with that?  Well, the <=> comparator function (also known informally as the “spaceship operator”) returns either -1, 0 or 1, depending on whether the first value is less than, equal to, or greater than the other.  The block will return the last statement evaluated.  So what happens is we compare species, then we then compare type, and it is always the result of the type comparison, -1, 0 or 1, is returned from the block.  The problem is, if species is not equal, then we want to stop there and return -1 or 1 accordingly and not evaluate type at all.

A simple way to do this is to add “if result==0” to the end of the type comparison, and only evaluate type if species was equal.

>> fishes = Fish.find(:all) 

>> fishes.sort do |a,b|
?>   result = a.species <=> b.species
>>   result = a.type <=> b.type if result == 0 
>>   result
>> end

This way, it will perform the first search by species, then only continue to perform the secondary search if the result of the first search was zero, that is they were equal values. And so I end up with a list like:

species type
Guppy Fancy Tail
Molly Dalmation
Platy Calico
Platy Mickey Mouse
Platy Rainbow
Platy Sunset
Posted in code. Tags: , . 2 Comments »

Ruby Sorting [1] – When and Why to use sort_by()


When I read the rdoc on sort_by, I understood the general idea that sort_by is more efficient in some situations. The specifics on why were still over my head, so I wasn’t planning to get into specifics during my recent talk on sorting. Yet just a few hours before my talk Jim Weirich was still trying to cajole me into using big words like “Schwartzian Transformation” in my talk because, he teased, “using big words makes you sound important :)”

The good thing is that this gave me a chance to talk it out with him, and actually understand it for real. It was too late for me to add that into my talk a few hours before I was to give it, but I do want to talk about it here now that I understand.

sort_by() is good if the values you’re sorting on require some kind of complex calculation or operation to get their value.

Let’s say you have an aquarium, and you save the dates of when each fish is born in a database. Later, you want to sort the list of fish by age. But you must calculate the age based on the birth date. So the Fish class has an age method:

class Fish
...
  def age
    (Date.today - birthday).to_i
  end
end

So when you sort like this:

>> fishes = Fish.find(:all)

>> fishes.sort do |a, b|
>>   a.age <=> b.age
>> end

It will calculate age over and over as it sorts. And if you’ve studied sorting algorithms, you know that the items in the list are compared with other list items repeatedly until it can be determined where the items go in the ordered list. So using this way of sorting, the age will be calculated a lot!

When you use sort_by() instead:

>> fishes.sort_by do |a|
>>   a.age
>> end

It does 3 things:

1. It will first go through each item in fishes, calculate age, and put those values into a temporary array keyed by the value. Let’s say we have 3 fish, one 300 days old, one 365 days old, and one 225 days old. The temporary array looks like this

[[300, #<Fish:A>][365, #<Fish:B>][225, #<Fish:C>]

2. The complex calculation is now done, once for each fish. It sorts this temporary array by the first item in each sub array. Meaning, it sorts by the numbers 300, 365 and 225, without recalculating them.

[[225, #<Fish:C>],[300, #<Fish:A>][365, #<Fish:B>]]

3. Lastly, it goes back through the array, grabbing the 2nd array elements (the actual Fish objects) and putting them in order into a flattened 1-dimensional array

[#<Fish:C>, #<Fish:A>, #<Fish:B>]

So, that is how you end up with a sorted array without recalculating values more than you need to. And that is why sort_by() can be more efficient.

Posted in code. Tags: , . 1 Comment »

Ruby Sorting [0] – Sorting a Hash


It figures that one of the questions someone asked, following my talk on sorting last month, was something I specifically chose not to cover for the sake of time, and to be able to cover more valuable topics. So, when someone asked whether you can sort a Hash and how, I knew A) that you can, and B) I knew I had barely glanced at it in the rdoc on hash sorting, but didn’t remember how it worked. So I had to simply suggest they go read about it themselves. But I was also curious to go read about it more myself.  So I took my own advice, and here’s what I came up with:

I define a hash:

irb(main):001:0> typical_fish_colors =
irb(main):002:0*    {"clownfish" => ["orange","white","black"],
irb(main):003:1*     "goldfish" => ["orange"],
irb(main):004:1*     "angelfish" => ["black","white"]
irb(main):005:1>    }

Default sorting on a hash – sorts the keys.

Pretty simple I guess. What you may not expect, depending on what you know of hashes, is that you don’t get a Hash object returned from calling .sort, you get an Array.  A nested, three-dimensional Array. This is because arrays are ordered, hashes are not.

irb(main):006:0> typical_fish_colors.sort
=> [["angelfish", ["black", "white"]], ["clownfish", ["orange", "white", "black"]],
   ["goldfish", ["orange"]]]

What you can’t do when sorting a hash is use sort! (sort-bang):

irb(main):007:0> typical_fish_colors.sort!
NoMethodError: undefined method `sort!' for #<Hash:0x2d17ea8>
 from (irb):7

What else you can’t do when sorting a hash by default is use symbols for keys:

irb(main):008:0> typical_fish_colors =
irb(main):009:0*     {:clownfish => ["orange","white","black"],
irb(main):010:1*      :goldfish => ["orange"],
irb(main):011:1*      :angelfish => ["black","white"]
irb(main):012:1>     }

irb(main):013:0> typical_fish_colors.sort
NoMethodError: undefined method `<=>' for :clownfish:Symbol
 from (irb):13:in `<=>'
 from (irb):13:in `sort'
 from (irb):13
Posted in code. Tags: , . Leave a Comment »

On Sorting in Ruby

After speaking at the Columbus Ruby Brigade last month on the topic of Ruby sorting, I’ve gotten a chance to use some of the sorting techniques I spoke about more over the last month at work. There were a few things I didn’t get a chance to cover since I was only giving a 5-10 minute lightning talk. There’s a few things I’ve come to understand a little better (benefits and gotcha’s) since then.

Things I talked about (feel free to check out the slides from my talk for examples of some of these things)

  • Basic sorting with .sort and .sort!
  • Sorting your own complex types by defining a <=> method on your class
  • Sorting on the fly with blocks
  • Sorting nested objects

Things I did not cover for various reasons. And blog posts covering them in more detail after the fact:

Posted in code. Tags: . Leave a Comment »

Using Selenium to check for the presence of an image

I spent a little bit of time yesterday trying to figure out how to use Selenium to check for the presence or absense of a specific image used as the background of an HTML table.  It wasn’t that hard to do in the end, but I got a little tripped up trying to check for the wrong thing.  Pretty cool once I got it done, so I figured I’d share here.

What I tried to do:

At first I tried to grab the HTML text inside the TD and verify the presence of the filename of the image as text.

What I should have done all along:

What ended up working was that I knew the table row and cell in which I was expecting the image, and I had to do a “verifyElementPresent” instead. (Thanks to Dean for helping me figure that out)

fishsel

 

The only thing I don’t like about that approach (vs. checking for text) is that I can’t do a wildcard search for the text.  I have to exactly check for the full path to the file.  So, if we decide to re-organize the directory structure and move some images to a “saltwater” and some to a “freshwater” subdirectory, the selenium test is then fragile and breaks.  But chances are the images are going to remain pretty static, so I am happy enough with this approach.

Posted in code. 6 Comments »