Project Ramon

A learning journey from a Ruby noob perspective

Lunch Panoply: The Controller & Spec Refactor

lunch_panoply5_header_img

Today I’ll be wrapping up my refactors with a controller_spec and it’s associated controller.

I’ll be primarily looking for areas to eliminate redundancy, as well as making sure each spec looks like an easy and descriptive read at a glance.

Before we get started, I’ve stumbled upon some resources about testing controller specs, they are:

  1. This StackExchange post
  2. And this StackExchange post

Refactoring The Controller Specs

First lets take a look at the companies_controller_spec file before any changes are made:

lunch_panoply5_img

We can see from the illustration above that I’ve already extracted the factory object calls from each spec, replacing them all with a single call to let on line: 4. Lets see if we can’t find any additional unnecessary code duplication.

If you remember from yesterday’s post, I replaced a few arrays for the index action. Here though, we only see one array defined in our specs so I’m inclined to leave this as is.

We can see duplication however, in the index and new actions we’re passing the HTTP verb GET as well as the factory objects ID attribute in three places in the above example. Lets reduce these by using a before filter.

lunch_panoply5_img2

I decided to change my factory object’s name inside of the spec it 'populates an array of companies' on line: 17, the unique name prevented me from using the let(:company) { create :company }. I’ve also added a before filter in both the index and new actions on lines: 7 & 25 and commented out the redundant expressions for demonstration. Lets see if our specs still pass before completely removing the commented out redundant code.

lunch_panoply5_img3

It does! So lets remove those commented out lines, and move towards tackling the associated companies_controller file.

Refactoring the Controller

lunch_panoply5_img4

This illustration shows the only redundant controller code in the file. It’s a simple fix, as our only task is to remove all of the duplicate instance variable calls. We can extract these into one tidy private method. Making the method private will give us an added advantage of not allowing the get_company instance method available to outside classes. I remember a very helpful analogy that I read in Sandi Metz’ book Practical Object-Oriented Design in Ruby. It was an analogy about a restaurant, and the parallel of thinking of public instance methods as the servers and the private methods as the kitchen staff. Analogies like this has made understanding Object Oriented programming much easier for beginners like myself to understand!

There are two steps to our refactor of the CompaniesController class. Step1 is to create the private method and remove the duplicate code. Step2 is to create a before filter specifying witch controller actions this method should be used before the code inside of the action methods are ran.

Lets get to implementing steps 1 of 2. Creating this one private method:

lunch_panoply5_img5

Now we could just call the get_company method in the controller actions and that would be considered a refactor. And although it does slightly improve our code any seasoned Rails developer will quickly point out that I’ve only gone half-way, why type a method call out when we can use a before filter to achieve the same result.

Note: Whats the difference between before_filter and before_action?

Nothing, in Rails 4 before_action is synonymous to before_filter, I found this StackOverflow post sharing that before_filter isn’t even depreciated. It’s basically just new syntax, and although I don’t know the exact reasoning, I’d guess that it just makes more sense when reading it. Before an action do ‘x’, does read better than before filter do ‘x’.

Back to our final step in our CompaniesController class we can add the before_filter, as I’m using Rails 3.2.16 for this project:

lunch_panoply5_img6

Here I’m using the except option to select the controller actions that should not receive this filter. I could have used only to achieve the same results, listing only the actions that should receive the filter, but since except is slightly quicker to write, I went with that.

And there we have it, a newbie’s refactor of a controller_spec and it’s associated class.

I hope that you all have a wonderful weekend!

Stay tuned…

Advertisements

Categories: Uncategorized

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s