Denis Bolomier
Denis Bolomier

Reputation: 450

Get a enum with rails 7

On Ror 7.0, with postgres, I have a model created with the following migration:

create_enum :examen_cpf, ["attente formation", "attente qcm", "attente evaluations", "terminé"]
create_table :examen_cpfs do |t|
  t.enum :state, enum_type: :examen_cpf, default: "attente formation", null: false
end

in a model I want to list the enum. How can I get it ? I try:

Thanks for your help

Upvotes: 0

Views: 112

Answers (2)

Greg
Greg

Reputation: 6659

The enum support (or rather integration between) Rails and database is probably not as good as you assume.

I have a model created with the following migration:

create_enum :examen_cpf, ["attente formation", "attente qcm", "attente evaluations", "terminé"]
create_table :examen_cpfs do |t|
  t.enum :state, enum_type: :examen_cpf, default: "attente formation", null: > false
end

This is not exactly correct. This code does not create a model. You're using Ruby's migration's DSL to define PostgreSQL's enum type, and then create a table with a field of that enum type.

I believe this is as far as this integration goes. I don't think ActiveRecord is capable of fetching the possible enum values from the DB (as it's capable of retrieving the fact that the column is a string, or int and cast it correctly). So you still would need to use ActiveRecord::Enum and "tell" your model:

class ExamenCpf < ApplicationRecord # ExamenCPF depending on your inflections
  enum :state, ["attente formation", "attente qcm", "attente evaluations", "terminé"].to_h { |v| [v, v] }
end

And then ActiveRecord will provide you with a method (pluralized version of the column name, here #states) which you can use to list all of the enum values

> ExamenCpf.states
# => {"attente formation"=>"attente formation", "attente qcm"=>"attente qcm", "attente evaluations"=>"attente evaluations", "terminé"=>"terminé"}

If you hate the idea of repeating yourself like that, check the other answer on how to fetch the ENUM values, maybe with a little bit of determination you could connect those two approaches and do something like

  enum :state, enum_values_for(:examen_cpf) # plus usual ActiveRecord::Enum.enum goodies available via options for that method)

Upvotes: 0

Ola Tuvesson
Ola Tuvesson

Reputation: 5221

While I haven't been able to find a native Rails way to retrieve a list of the possible PostgreSQL enum values, I thought I'd share the raw SQL query I ended up using instead. In my model I added a pluralised method for the attribute in question, which executes a query directly on the DB connection:

  def myenums
    ActiveRecord::Base.connection.exec_query("select enum_range(null::myenum)").cast_values.flatten
  end

This allows me to fetch the possible enum values for a model attribute:

myapp(dev)> mymodelinstance.myenums
  SQL (1.3ms)  select enum_range(null::myenum) /*application='MyApp'*/
=> ["one", "two", "three", "four"]

This isn't an ideal solution, and I'd love to hear if there's a native Rails way to do the same, but it'll have to do for now.

Upvotes: 1

Related Questions