0

I have a class constant in my Rails app for mapping integers from a column to strings:

TYPES = [[1, "Beginner"], [2, "Intermediate"], [3, "Advanced"]]

I can use this to convert the integers to a human-readable strings for instances of the model (e.g., TYPES.to_h[type_id]), but I'd also like to use it to SELECT the human-readable string for large numbers of records at once. I could use a CASE statement:

SELECT *, CASE WHEN type_id = 1 THEN 'Beginner'
     WHEN type_id = 2 THEN 'Intermediate'
     WHEN type_id = 3 THEN 'Advanced'
END AS type_string FROM users;

However, this becomes very verbose, difficult to manage, and time-consuming as the TYPES array gets even slightly longer. Is there a better, more efficient way to select the type string from the type_id?

2
  • Are you looking something like enums. What enum does for you is it associates a symbol list for you to reference which will be stored in the database as an integer. So :cow could be 0 and :dog could be 1 in an enum of [:cow, :dog] . Reference link 6ftdan.com/allyourdev/2015/03/31/rails-4s-awesome-enums Commented Sep 1, 2015 at 16:59
  • @muistooshort I actually need to ORDER BY the strings for an admin view, which is the only case I need the strings in a db query. Should I be thinking about this in a different way? Commented Sep 1, 2015 at 17:17

2 Answers 2

1

Your need create the mapping on your db instead of rails.

Create table types as (
   type_id Int,
   name varchar(100)
)

With this you can add/delete/update types and your code wont break

Then join both table with this one

SELECT u.*, t.name
FROM users u
inner join types t 
    on u.type_id = t.type_id

If need the mapping in rails you do a

select * from types

and initialize your TYPES variable.

Sign up to request clarification or add additional context in comments.

1 Comment

So this is actually how I initially set it up, but my team is requesting a change to using the class constant so the logic isn't dependent on the state of the database. I'm resistant to this however, and maybe initializing the TYPES variable from the database provides a good middle ground, but I'd still like a solution to my initial problem for comparison...
1

You can always make another model (be careful using the reserved word 'type' in rails). ActiveRecord is great for these things. Don't store this data in code, especially if you need to sort it or it may grow. You can make a UI for managing the experience levels in an admin namespace that's restricted to common users.

This example uses the class name ExperienceLevel.

class ExperienceLevel < ActiveRecord::Base

  has_many :users, foreign_key: "type_id"

  # has an attribute called 'name'

end

Add the association to User

class User < ActiveRecord::Base

  belongs_to :experience_level, foreign_key: "type_id"

end

And then refer to it in rails views as you'd expect

@user.experience_level.name

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.