Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing a lookup table in Rails

I'm currently using (or trying to use) a lookup table to represent a column that contains an enumerated string. I've had extensive discussions with my team to make sure this is the direction we want to go and have decided to pursue it but unfortunately none of us know how to tie the lookup table to the column using migrations and if there are changes that have to be made in the model/controller/views to support this new behavior.

I've googled this extensively and have not found good examples of doing this so I'm hoping someone can either tell me of a wonderful link to a tutorial I just missed in my search, or describe how to do this. I also would love to know if there is an unofficial (or official) Railsy pattern for this.

Thanks in advance.

like image 636
jaydel Avatar asked Jan 28 '11 13:01

jaydel


3 Answers

If you're looking for a light-weight way to model enumerations/configuration without creating a separate table, definitely check out ActiveHash:

https://github.com/zilkey/active_hash

like image 196
Winfield Avatar answered Nov 20 '22 02:11

Winfield


I encountered the same problem as you, and solved it by creating a gem that adds a dynamic lookup table transparently into the model. I've blogged about it here: http://www.codelord.net/2011/08/09/guest-post-lookup-tables-with-ruby-on-rails/

And the code is here: https://github.com/Nimster/RailsLookup

like image 3
Nimrod Priell Avatar answered Nov 20 '22 01:11

Nimrod Priell


I know this is an old question, but since it's still the top hit on google, I thought I'd share my solution to it which is packaged up as a gem. Take a look at https://github.com/blackrat/acts_as_enumeration

From the readme:

So if a database table had a column called "name", declaring

acts_as_enumeration :name

would select all of the items in that column and map them in a hash to their primary key values.

In addition, it creates the instance methods is_#{key} where key is all of the values in that column, is?(array) and is_not?(array) that check for type within that array.

Keeping name as our column example, the class methods id_for_name will return the primary key value for that mapping and valid_name?(value) will say if the table contains and entry in the name column with that value.

Finally, the method missing allows for is_ and is_not chaining of methods, such as is_paul_or_michael_or_luke? which has the same effect as (is_paul? || is_michael? || is_luke?) or is?(:paul, :michael, :luke) and is_not_paul_or_michael_or_like which has the same effect as !(is_paul || is_michael? || is_luke?) or !is?(:paul, :michael, :luke)

CAVEAT: Due to the mechanism that the method_missing uses, if someone actually had the name "not bruce", the combination query cannot use this as the first element. i.e. "not " not just "not bruce".

So a combination of is_not_bruce_or_paul? would have to be written is_paul_or_not_bruce? to have the desired effect. is_not_not_bruce_or_paul is fine, but the chances of this happening are about as likely as someone actually called "not bruce" outside of a Monty Python sketch.

(Which means it probably will, so before you change code to support a new entry, try just changing the order)

like image 1
blackrat Avatar answered Nov 20 '22 01:11

blackrat