136

I have a enum in my Model that corresponds to column in the database.

The enum looks like:

  enum sale_info: { plan_1: 1, plan_2: 2, plan_3: 3, plan_4: 4, plan_5: 5 }

How can I get the integer value?

I've tried

Model.sale_info.to_i

But this only returns 0.

2
  • Shouldnt it be Model.sale_info.value.to_i? e.g. Model.sale_info.plan_1.to_i Commented Aug 29, 2014 at 14:21
  • Nops... Because I don't know which plan its store at database. So I want to recover it and cast it as an integer Commented Aug 29, 2014 at 14:22

6 Answers 6

173

You can get the integer values for an enum from the class the enum is on:

Model.sale_infos # Pluralized version of the enum attribute name

That returns a hash like:

{ "plan_1" => 1, "plan_2" => 2 ... }

You can then use the sale_info value from an instance of the Model class to access the integer value for that instance:

my_model = Model.find(123)
Model.sale_infos[my_model.sale_info] # Returns the integer value
Sign up to request clarification or add additional context in comments.

1 Comment

I like this approach. When using before_type_cast, it’ll return a string if you’re on an unsaved record you’ve initialised like Post.new status: :unapproved, but an integer if it’s persisted.
169

You can get the integer like so:

my_model = Model.find(123)
my_model[:sale_info] # Returns the integer value

Update for rails 5

For rails 5 the above method now returns the string value :(

The best method I can see for now is:

my_model.sale_info_before_type_cast

Shadwell's answer also continues to work for rails 5.

2 Comments

It is because 'enum' will create a method sale_info for your model, use [:sale_info] to get the property value instead of return from sale_info method.
Note that this method does not work if the model has not been saved. The sale_info_before_type_cast value (and my_model[:sale_info]) is still a string if it my_model.sale_info has been assigned a string without a subsequent save.
68

Rails < 5

Another way would be to use read_attribute():

model = Model.find(123)
model.read_attribute('sale_info')

Rails >= 5

You can use read_attribute_before_type_cast

model.read_attribute_before_type_cast(:sale_info)
=> 1

2 Comments

@GrantBirchmeier Updated the answer. You can use read_attribute_before_type_cast.
Before Rails 5, model.read_attribute('sale_info') equal to model[:sale_info]
6

My short answer is Model.sale_infos[:plan_2] in case if you want to get value of plan_2

Comments

6

I wrote a method in my Model to achieve the same in my Rails 5.1 app.

Catering for your case, add this into your Model and call it on the object when needed

def numeric_sale_info
  self.class.sale_infos[sale_info]
end

Comments

0

Most of the solutions here require you to have a record or model class in hand. Here is an approach where you can get the integer value from an enum without creating a record, by using Hash's .key method:

sale_info.key('plan_3')
=> 3

This is particularly useful if you're doing some ETL and mapping raw values to/from string values between systems that depend on the numeric integer value and/or the string value in different scenarios.

Note that this is probably not highly performant, as searching for a value in a hash (as opposed to a key) is not efficient. If you're processing millions of values/second or have an enum with (yuck) hundreds of values, you'll probably want to build a new hash that inverts enum's values and keys so you can do efficient lookups in the opposite direction.

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.