Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Rails, how should I implement a Status field for a Tasks app - integer or enum?

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:

Rails Schema Here:

create_table "tasks", :force => true do |t|
t.integer "status", :limit => 1, :default => 0, :null => false

Rails Model Here:

class Task < ActiveRecord::Base   validates_inclusion_of :status, :in => 0..2,     :message => "{{value}} must be 0, 1, or 2" 

Rails View Here:

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

Requirements

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

  2. Solution must work with Rails 3.0.

Questions:

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

  2. Should I use an enum? If so, is this easy to localize later?

  3. Should I use straight strings, e.g. "Normal", "Active", "Completed"

  4. Can you provide a quick code sample of the view helper, controller or view code to make this work?

like image 472
Doug Avatar asked Apr 16 '10 05:04

Doug


1 Answers

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 ','}" 
like image 50
Vlad Zloteanu Avatar answered Oct 04 '22 05:10

Vlad Zloteanu