MVC – Controller

The C in MVC stands for controller.

In previous weeks we have looked at both the Model and the View layers. We know that the model retrieves data out of the database and that the view displays that data. But how does the model know what data is required and how does the data get passed back to the view? That is where the controller comes in.

In the same way that every object in our application has a model and a number of views, each object also has a controller. The Controller is responsible for orchestrating the whole process of handling a request in Rails.

The routes.rb file maps an external request from a URL entered into a browser to an internal action within your Rails application. That internal action is a method in a controller. The controller may also contain logic to implement business rules.

MVC – View

This is the second post in the series. Check out last weeks post on the MVC – Model layer.

The V in MVC stands for view.

When we look at a web page what we are looking at is an HTML document.

Every object in our web application will need a number of HTML documents associated with it. To continue with our shopping application from last week, let’s take Product as an example.

We will need a page for each of the following: * a listing of all the products available for purchase * detailed information about a single product * a page for entering a new product * a page for editing an existing product

Each of these pages are referred to as a view in Rails-speak and belong in the View layer.

A view in a Rails application contains both HTML and Ruby code. The file will have .html.erb as it’s extension. The .html is self-explanatory: it, like every other web page, contains HTML. The .erb means that the file (possibly) contains embedded Ruby. This embedded Ruby allows us to include logic into an otherwise static HTML page.

MVC – Model

We keep hearing MVC referred to when talking about Rails. But what does it really mean? Over the next three weeks we’ll cover each component in detail.

The M in MVC stands for model.

Every web application that has anything other than very basic functionality will have a database behind it. And every object in our application will be represented by a table in that database.

So, for example, in a shopping website we will need to store information about our products and the customers who buy those products. Each time a Customer buys a Product it will generate a Transaction. This Transaction will also need to be stored in the database. So our database will have (at least) three tables: customers, products and transactions.

A model is that part of your Rails application whose job it is to talk to the underlying database. So, in our Rails application above, we will need to have three models: Customer, Product and Transaction.

When we need to obtain data about any of these three objects, we will ask the relevant model. That model will in turn ask the database.

Check out the next post in the series, MVC – View.

ActionController

The magic that is ActionController

We use controllers a lot in our applications but do we really understand the magic that is behind them?

Controllers are considered to be the middleman between the model and the view. Most inherit from ApplicationController. But did you know that ApplicationController inherits from another controller called ActionController::Base?

By using inheritance, (that’s the < ApplicationController bit) we gain a whole lot more functionality that we can use in our app.

ActionController::Base is part of the Rails library Action Pack. It is the base class for all controllers in a Rails application. It provides many helper methods including the filtering of inbound http requests, access to our model, and rendering a view. But there are many more, see the rails API for more info.

Below is a simple example of how it might look. It looks like it is doing very little. In fact, it is doing a lot! It is getting the params from the url, asking our model for that record (using the id) and then rendering the show.html.erb view.

class IdeasController < ApplicationController
  def show
    @idea = Idea.find(params[:id])
  end
end

Easy huh?

Migrations

Rails Migrations

Recently I came across an issue with a database migration that could easily have been avoided.

I was querying a database that contained a number of boolean NULL values. This is ambiguous, as it could mean false or it could simply mean that the value has never been set.

This scenario is easily avoided by simply setting your boolean to either true or false as a part of your migration. For example;

add_column :staff, :is_admin, :boolean, null: false, default: false

That’s it! Easy right? It may not change your life but it will surely avoid a headache somewhere down the track.

$LOAD_PATH

What Is $LOAD_PATH (also known as $:)

I have come across $LOAD_PATH many times and have always skipped over it, never quite understanding what it meant. Well, that is, until recently. The project that I am working on forced me to take a closer look. And once I did, like most things, it really wasn’t that difficult at all.

The first thing to understand is what it refers to. Quite simply $LOAD_PATH is what Ruby uses to determine which directories to look in when you use require in your code. In other words, $LOAD_PATH contains nothing more than lots of directories. Easy, huh?

The second thing you should know is how to reference it. You can refer to $LOAD_PATH in two ways. The first way is to simply call it by its name, $LOAD_PATH.

The second way is to use the predefined variable, $:

Both mean the exact same thing.

Finally to see it in action, here is an example of adding a directory to $LOAD_PATH

$: << File.expand_path('../', __FILE__)

RSpec

1. Equality Matchers

I have been working on an upgrade from Rails 2.3 to Rails 4.2. Along with the multitude of changes involved in such an undertaking, there is also the change from RSpec 2 to RSpec 3.

Two things had me particularly confused, and caused many failing specs until I figured out why.

RSpec offers no less than three similarly-names equality matchers: eq, eql and equal.

After getting used to Ruby’s so-called ‘syntactic sugar’, I have become lazy in looking up syntax. Oftentimes, whatever you think it might be, it is. So I assumed that the three different options for equality matchers were just that: options. Pick whichever one you like and go with it. Oh, how wrong I was! It turns out there is a world of difference between them:

expect(a).to equal(b)

This states that the object referred to by a is expected to be the exact same object referred to by b.

expect(a).to eql(b)

This states that the object referred to by a has the same value as the object referred to by b.

expect(a).to eq(b)

This states that the object referred to by a has the same value as the object referred to by b, and it will perform a type conversion if necessary. This means that if a contains the value 3 and b contains the value 3.0, it will return true.

2. be Matchers

Again, RSpec offers no less than three similarly-names equality matchers: be_true/be_false, be_truthy/be_falsey and be true/be false. Luckily with RSpec 3, we are now down to two (see below).

Here there is a subtle difference that can cause all manner of unexpected behaviour if you choose to overlook it.

expect(a).to be true

passes only if a == true

expect(a).to be_true

passes if a is anything other than nil or false

expect(a).to be_truthy

passes if a is anything other than nil or false

expect(a).to be false

passes only if a == false

expect(a).to be_false

passes if a is either nil or false

expect(a).to be_falsey

passes if a is either nil or false

As you can see be_true and be_false are the same as be_truthy and be_falsey. In RSpec 3, there is no longer be_true and be_false so it is a little less confusing now.

RESTful Constraints

REST (representational state transfer) is a big topic so we won’t attempt to cover it all in this post. Firstly, it’s a very important topic and secondly, we don’t want to bore you with too much info. That’s just not the Rails Girls style! 🙂

This post will focus on the constraints of REST. We will cover the top four constraints.

1st Constraint

Client / Server: We need to follow the client/server architecture. The purpose of the client is to make the request and the server to respond to it. Straightforward enough!

2nd Constraint

Stateless: This means that the full interaction should be enclosed in the request and response exchange. For example, we ‘request’ a resource from the server and the response returns all the requested information in a single interaction. Not too tricky either!

3rd Constraint

Resources: For any resource in our app, we should be able to access this resource via a stable url. For example, to get the Idearesource in our Rails Girls app, we used the url www.example.com/ideas. If we had a different app with aProduct resource, we would use the url www.example.com/products.

To comply with this constraint in a Rails app, simply define your resources in your routes.rb file by using either resource or resources. This will automatically give you all the standard RESTful routes with their corresponding standard urls.

4th Constraint

Manipulation through representations: The manipulation part of this constraint refers to the HTTP verbs included in the request (GET, PUT, POST and DELETE). The representations parts refers to the different formats your rails app might respond with (eg. JSON, XML or HTML). We have a useful helper that we can use in our controllers for different responses:

respond_to do |format|
  ..different formats
end

The important point to note is that, regardless of the response format, the url stays the same. That’s pretty impressive!

And that is our first high-level introduction to REST. We have more to cover over the coming weeks so stay tuned! To read more to get a better understanding we encourage you to read this resource

RESTful Rails

Recently I decided to add a new download file feature to the Rails Girls Ideas app. It seemed like a straightforward task. But, upon opening the routes.rb file, I realised I there was more to this decision than I first thought. I had to decide on the type of route…should I create a member route or a resource route?

What is a Member Route

A member route simply adds an additional action to the enclosing resource.

The example below adds a new file action to the existing ideas controller (ideas_controller.rb). In this case the file relates to a single idea. The url to access it would be something like /ideas/1/file

# routes.rb

resourses :ideas do
  member do
    get :file
  end
end

# ideas_controller.rb

class IdeasController < ApplicationController
  def file
   # download code here
  end
end

However I started to think about what else I might need to do with the files: What if I want to add some more methods? What if I want to rename the file, or tag the file? What if I want to add a method to delete the file? And if I add all this new functionality, does it still belong in the ideas_controller?

Why a Resource Route

In order to keep controllers from becoming bloated, you can put the new action into its own controller. Then if the situation arises where you want to extend the functionality of the controller and add methods such as upload/download/rename/tag/delete actions you are already in the right place.

# routes.rb

resources :ideas do
  resource :file, only: [:show]
end

# creating the new method in its own controller

class FilesController < ApplicationController do
  def show
    #download method
  end
end

The url to access it is still something like /ideas/1/file. The only difference lies in the fact that file is now an entity all of it’s own and, as such, has it’s own controller.

Remember when in doubt type rake routes at the command line to find your way. It will show you the http verbs, the controller and corresponding action and also the url helpers

I should point out that using a resource route is considered more RESTful than a member route. However understanding the difference is the key, as it will guide you in making an informed decision 🙂

Testing Explained

At Rails Girls we like to talk about tests. In fact, pretty much all Rails developers like to talk about tests! Why is this? Well, we understand how important they are to making your code as robust and error-free as possible. But we also understand how confusing they can be..there seems to be so many different types of tests. We believe most things in Ruby on Rails are only confusing because they haven’t been explained properly. In this post we are going to very simply explain tests. Once you understand what they are, the syntax isn’t really that hard..trust us!

Unit Tests

These tests are generally very quick and precise. They test at the method level and they generally test one single thing. An example might be testing that a specific data attribute has a valid value. A good rule of thumb is that whenever you add any new feature you write a unit test for it.

Integration Tests

These start one layer up from our unit tests and they test the underlying services. They are fantastic at telling you when something is broken, however they are not as precise as unit tests in telling us exactly what is broken. A perfect example of an Integration Test would be the testing of a valid and invalid login or perhaps connectivity to your database. The idea here is to flag when something is wrong rather than the low level of detail that unit tests can give us.

User Interface Tests

These tests are our end to end tests. They test the whole system and how it connects together with the UI. And in that sense they are fab. It can be tempting to think all testing should be UI tests but this is not the case. UI tests are very slow and therefore considered expensive. They can also be flaky which means that if something changes on the UI, even if it is just a new field, it could ‘break’ your tests. Don’t get us wrong, they are necessary and they have many benefits but use them sparingly.

Now we know we have covered a lot in one post but we will chip away at each type of test over time. So if you take just one thing from this post let it be this: when it comes to testing your app try to cover as much as possible with unit tests 🙂

Sorcha & Rachelle