Today we continue our analysis of the Rails Best Practices.
In the previous post we saw Named Scope, Model Association and
Following the same direction, in today’s post we’ll examine the use of Callback Model and Virtual Attribute.
1. Virtual Attribute
Suppose we have a customers list table defined as follows
1 2 3 4 5 6 | create_table "clients", :force => true do |t| |
Suppose we have a customers list table defined as follows but we want to define an input mask where street and city are grouped into one field called “address”.
The form with the “address” field will be defined as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <h1>Create Client</h1> |
Now in the create method we’ll have something like:
1 2 3 4 5 6 7 8 9 10 11 12 | class ClientsController < ApplicationController |
We can now improve this method by defining the address field as a virtual attribute of the Client model.
1 2 3 4 5 6 7 8 9 10 11 12 | class Client < ActiveRecord::Base |
In the form we can now define the address field as f.field_tag instead of as text_field_tag :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <h1>Create Client</h1> |
Finally, the controller will become simpler:
1 2 3 4 5 6 7 8 9 10 | class ClientsController < ApplicationController |
2. Model Callback
Now we see a method, called Model Callback that allows us, as with the virtual attribute just seen, to simplify the form and to move the controller’s logic inside the model.
Suppose we have to implement a feature that automatically associates a set of tags to a post.
This feature, called calculate_tags return a list of tags based on the most frequent words contained in the post.
We don’t see the code of this function and instead see how and when to invoke the automatic generation of tags.
A first implementation can be as follows. Given the following form:
1 2 3 4 | <% form_for @post do |f| %> |
the corresponding create method will be:
1 2 3 4 5 6 7 8 9 10 | class PostController < ApplicationController |
Editing the Post model, let’s see how to improve the code we’ve just wrote.
First we introduce in our model an attribute, “calculate_tags”, and a filter “generate_tags”, of type before_save
1 2 3 4 5 6 7 8 9 10 | class Post < ActiveRecord::Base |
Returning to the form we can now redefine the field calculate_tags as f.check_box
1 2 3 4 | <% form_for @post do |f| %> |
Finally, our create method in the controller will return to its simplest form.
1 2 3 4 5 6 | class PostController < ApplicationController |