Rails Best Practices 6: Filters and helpers file

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

1
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:

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
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

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
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:

1
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:

1
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:

1
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.

1
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.

Tags: , , , , ,


About Claudio

Claudio Marai is a co-founder of DevInterface.

After graduating in Computer Science has contributed to develop complex web applications based on Java/J2EE and desktop applications with the. NET framework for the Ministry of Justice and ultimately for the banking ambit.

The passion for web in recent years has led him to be interested in more modern frameworks such as Ruby on Rails and Django, and to a development approach based on agile methodologies such as eXtreme Programming and SCRUM.

About DevInterface

We are an information and communication technology agency. Our mission is to provide web application development, design services and communication strategies. We specialize in building web applications with modern and efficient frameworks.

Related Post

2 Responses to “Rails Best Practices 6: Filters and helpers file”

  1. [...] This post was mentioned on Twitter by Hugo Roque, DevInterface. DevInterface said: "Rails Best Practices 6: Filters and helpers fileRails Best Practices 6: Filtri e file helper" – http://bit.ly/djxFTA #rubytweets [...]

  2. SteveD says:

    There’s a lot of controller code that should be in a model:


    class ApplicationController < ActionController::Base

    def add_log
    ActivityLog.log_access(self, request)
    end

    #other methods here

    end

    class ActivityLog request.session_options[ :id],
    :user_id => controller.current_user.id,
    :browser => request.env['HTTP_USER_AGENT'],
    :ip_address => request.env['REMOTE_ADDR'],
    :controller => controller.controller_name,
    :action => controller.action_name,
    :request_at => Time.now,
    })
    end

    end
    </code.

Leave a Reply

Insert code beetween <code lang="ruby"> and </code>

Copyright 2012 DevInterface s.n.c.

DevInterface Blog is proudly powered by WordPress