Rails Best Practices 3: Increase Controller’s readability

[POST UPDATE ON 19/07/2010 - 15:45]
Continuing our analysis of the Rails Best Practices today we’ll see two other tricks to make more readable method of the controller.

1. Methods within model

Suppose we have the classic user registry defined in such a way that an admin user can enable or disable other users.

The deactivate method inside user Controller may be defined as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

class UserController < ApplicationController

def deactivate
@user = User.find(params[ :id])
if @user.admin?
flash[:error] = "You can not deactivate Admin user"
else
if @user.update_attributes(:status, "N")
@user.modified_by = current_user
@user.save
else
flash[:error] = "Error during user deactivation"
end
end
redirect_to :action => 'index'
end

end

What is clear is that this method has a lot of business logic inside. We see then how to define a method in the User Model to implement business logic so we can streamline this method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

class User < ActiveRecord:Base

def deactivate(user)
ret = false
if self.update_attributes(:status, "N")
self.modified_by = user
self.save
ret = true
end
ret
end

end


class UserController < ApplicationController

def deactivate
@user = User.find(params[ :id])
if @user.admin?
flash[:error] = "You can not deactivate Admin user"
else
if !@user.deactivate(current_user)
flash[:error] = "Error during user deactivation"
end
redirect_to :action => 'index'
end
end

end

This rewrite makes the deactivate method within Controller more readable and more easily testable.

2. Factory Method
In a similar way to what has been done for the deactivate method, sometimes can be handy while writing a create method, to define a Factory Method in the model that contains the logic of creation / initialization of the object and then call it from the controller.
As usual, let’s see an example.
Imagine you are developing a new management system where a news must be associated with the user who created it and it must also be visible only for a week.
A solution, without the Factory Method is the following:

1
2
3
4
5
6
7
8
9
10

class PostController < ApplicationController

def create
@post = Post.new(params[:post])
@post.user = current_user
@post.expiring_date = Time.now + 7.day
@post.save
end

end

Let us now see how to define a proper method (the Factory Method) of creating the news in the model so, once again, we simplify the controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

class Post < ActiveRecord:Base

def publish_new_post(params, user)
post = Post.new(params)
post.user = user
post.expiring_date = Time.now + 7.day
post.save
end

end

class PostController < ApplicationController

def create
@post = Post.publish_new_post(params[:post], current_user)
end

end

Once again we managed to write a better code in the Controller by moving the logic in the Model.

This post concludes the first part of this series when I tried to illustrate some best practices that allow to simplify the controller and move the business logic in the Model.

From the next post I will start to illustrate some Best Practices applicable to the Models.