For a Rails 3.0 Todo app, I have a Tasks model with a Status field. What's the best way to store the Status field data (field type) and still display a human-readable version in a view (HTML table)? Status can be:
0 = Normal
1 = Active
2 = Completed
Right now I have this:
create_table "tasks", :force => true do |t|
t.integer "status", :limit => 1, :default => 0, :null => false
class Task < ActiveRecord::Base
validates_inclusion_of :status, :in => 0..2,
:message => "{{value}} must be 0, 1, or 2"
<h1>Listing tasks</h1>
<table>
<tr>
<th>Status</th>
<th>Name</th>
<th></th>
<th></th>
<th></th>
</tr>
<% @tasks.each do |task| %>
<tr>
<td><%= task.status %></td>
<td><%= task.name %></td>
<td><%= link_to 'Show', task %></td>
<td><%= link_to 'Edit', edit_task_path(task) %></td>
<td><%= link_to 'Delete', task, :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
Store a Task's status in the db such that the values are easily localizable, i.e. I'm not sure I want to store "normal", "active", "completed" as a string field.
Solution must work with Rails 3.0.
Should I store the field as an integer (see above)? If so, how do I display the correct human readable status in an HTML table in my Rails view, e.g. show "Active" instead of "1" in the HTML table.
Should I use an enum? If so, is this easy to localize later?
Should I use straight strings, e.g. "Normal", "Active", "Completed"
Can you provide a quick code sample of the view helper, controller or view code to make this work?
1.It depends on how much you want to optimize queries on the DB.
2.Not really, it is not supported 'out of the box' by AR. # As of Rails 4 enums are supported out of the box.
3.IMHO you can use strings without a big performance penalty (just remember to add field to an index). I would do this because it's easier to internationalize and to maintain. However, you can go with integers if you need extra performance.
You may take a look on 2 SO threads here and here where this is debated.
4.If you want to keep them as integer, here is how you can accomplish this:
class Task << AR::Base
NORMAL = 1
ACTIVE = 2
COMPLETED = 3
STATUSES = {
NORMAL => 'normal',
ACTIVE => 'active',
COMPLETED => 'completed'
}
validates_inclusion_of :status, :in => STATUSES.keys,
:message => "{{value}} must be in #{STATUSES.values.join ','}"
# just a helper method for the view
def status_name
STATUSES[status]
end
end
and in view:
<td><%= task.status_name %></td>
If you want to use strings, it's more simplified:
STATUSES = ['normal', 'active', 'completed']
validates_inclusion_of :status, :in => STATUSES,
:message => "{{value}} must be in #{STATUSES.join ','}"