Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

In some ruby on rails projects, I have seen instances where strings are used instead of a foreign key reference to a lookup table.

I usually code in C#/SQL Server and use lookup tables, but am not particularly experienced in ruby on rails.

So my question is, should I be using strings instead of lookup tables in my ruby on rails web project (mysql and active record)? Is this something specific to ruby on rails, or to dynamically typed languages? Or for some particular circumstances? Or is it just bad database design?

By lookup tables I mean, like the following

UserStatus

Id    Name
1     Active
2     Disabled

User

Id    Username               UserStatusId
1     [email protected]   1
1     [email protected]   2

Whereas with just strings

User

Id    Username               UserStatus
1     [email protected]   active
1     [email protected]   disabled
share|improve this question
    
This is not very typical for Ruby on Rails. Though one may decide in some cases to avoid extra queries (most likely not very efficient, since a db would cache such small lookup tables anyway). Maybe if you have very complex data structures and want to avoid a few extra joins in complex queries?. There are better ways in Rails to do this (eg avoiding a table totally and writing a tableless model with this data in a hash if it's only a few strings anyway). –  thorsten müller Feb 26 at 11:33

1 Answer 1

up vote 2 down vote accepted

[EDIT] Ruby on Rails 4 enums

Rails 4 supports enums, so you can declare an enum attribute where the values map to integers in the database, but can be queried by name.

class Conversation < ActiveRecord::Base
  enum status: [ :active, :archived ]
end

conversation.archived!
conversation.active? # => false
conversation.status  # => "archived"

Conversation.archived # => Relation for all archived Conversations

Conversation.statuses # => { "active" => 0, "archived" => 1 }

Rails 3 and older

You could implement something like this:

USER_STATUS_VALUES = { 1 => :active, 2 => :disabled }

class UserStatus
  attr_reader :status_id

  def status
    USER_STATUS_VALUES[@status_id]
  end

  def status=(new_value)
    @status_id = USER_STATUS_VALUES.invert[new_value]
    new_value
  end
end

You would use it like this:

my_status = UserStatus.new

my_status.status = :new
puts "status: #{my_status.status}"
puts "status_id: #{my_status.status_id}"

Will return:

status: new

status_id: 1

Note: I could have used 'active' instead of :active but in this case, use of symbols is more appropriate.

share|improve this answer
    
So store the value in a database as an integer, but use the hashes to display/match them in the code? –  John Feb 26 at 16:19
    
Exactly. That way, you use it just like if there was a user_status table in the database. If you're using Rails 4, this is already implemented in ActiveRecord models with enum, see edit. –  raviolicode Feb 26 at 16:43

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.