With the today’s post I shall conclude my series on Ruby On Rails Best Practices . This is not because the required topics are completed, but rather because after the release of Rails 3.0, some constructs have been changed and should be reviewed.
Probably in future we will return to talk about best practices, but starting from the new features introduced in the current Rails version.
But now I will describe two techniques that are valid and which are mainly related to code organization.
1. Use filters
In order to remove duplicate code within the controller is good practice to use the filters to perform tasks that are common to most if not to all methods.
A classic case in which you use filters is user authentication.
Another example may be a function that makes the log of user activity.
I show here a very simple example for demonstration purposes only
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class ApplicationController < ActionController::Base
def add_log
#create new log
log = ActivityLog.new
# read data from request
log.session_id = request.session_options[ :id]
log.user_id = current_user.id
log.browser = request.env['HTTP_USER_AGENT']
log.ip_address = request.env['REMOTE_ADDR']
log.controller = controller_name
log.action = action_name
log.request_at = Time.now
# Save the log
log.save
end
#other methods here
end
We have defined our function add_log that saves data request in a log on db.
Now in our controller we will do something like this:
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
31
32
33
34
35
36
37
38
class PostController < ApplicationController
def index
add_log
@posts = Post.all
end
def new
add_log
@post = Post.new
end
def show
add_log
@post = Post.find(params[ :id]
end
def edit
add_log
@post = Post.find(params[ :id]
end
def create
add_log
@post = Post.create(params[:post]
end
def update
add_log
@post = Post.update(params[:post]
end
def destroy
add_log
@post = Post.find(params[ :id]
@post.destroy
end
end
The PostController can be optimized using a before_filter in the following way
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
31
32
33
class PostController < ApplicationController
before_filter :add_log
def index
@posts = Post.all
end
def new
@post = Post.new
end
def show
@post = Post.find(params[ :id]
end
def edit
@post = Post.find(params[ :id]
end
def create
@post = Post.create(params[:post]
end
def update
@post = Post.update(params[:post]
end
def destroy
@post = Post.find(params[ :id]
@post.destroy
end
end
Then if we want the calls to some methods (eg show and index) can not be traced we can simply define the filter as follows:
2
3
4
5
class PostController < ApplicationController
before_filter :add_log, :except => [:show, :index]
# methods
Obviously the use of filters should be done in a careful way because excessive use of before_filter or after_filter for operations not so general can make the code less immediate to understand.
2. Organize helpers by functionality
The second technique that I introduce today is a better system (in my opinion) to organize helper files.
Rails typically generates an helper file for each controller. So it’s easy that in a short time you have a large number of helpers and often you use only a few of them.
For example:
2
3
4
5
app/helpers/application_helper.rb
app/helpers/comments_helper.rb
app/helpers/posts_helper.rb
app/helpers/users_helper.rb
# ...
And in the ApplicationController:
2
3
class ApplicationController < ActionController::Base
helper :all # include all helpers, all the time
end
A system I find very convenient is rather to organize helpers for functionality, removing all unnecessary and empty files.
2
3
app/helpers/application_helper.rb
app/helpers/buttons_helper.rb
app/helpers/treeviews_helper.rb
In the ApplicationController you not need to change anything. As before it loads all the helpers in the helpers folder. The advantage of this solution is to have fewer helper files and know immediately where to enter or search for a method when you have to add or change it.