'Attribute not selected on edit page

I have Projects model:

class Project < ApplicationRecord
  acts_as_tenant :account
  has_rich_text :description

  validates :name, :progress, :priority, :status, presence: true

  # Broadcast changes in realtime with Hotwire
  after_create_commit  -> { broadcast_prepend_later_to :projects, partial: "projects/index", locals: { project: self } }
  after_update_commit  -> { broadcast_replace_later_to self }
  after_destroy_commit -> { broadcast_remove_to :projects, target: dom_id(self, :index) }

  enum priority: { no_priority: 0, low: 1, medium: 2, high: 3 }
  enum status: { not_started: 0, in_progress: 1, waiting: 2, done: 3 }

  def priority
    super.to_s.humanize
  end

  def status
    super.to_s.humanize
  end
end

On edit page I have this form:

<%= form_with model: @project do |form| %>

  <div>
    <%= form.label :name %>
    <%= form.text_area :name %>
  </div>

  <div>
    <%= form.label :priority %>
    <%= form.select :priority, [["No priority", "no_priority"], ["Low", "low"], ["Medium", "medium"], ["High", "high"]], selected: form.object.priority %>
  </div>

  <div>
    <%= form.submit %>
  </div>
<% end %>

Problem is, when I want to edit existing project, dropdown select element don't select option from database, but only first one.

Generated HTML:

<select name="project[priority]" id="project_priority">
  <option value="no_priority">No priority</option>
  <option value="low">Low</option>
  <option value="medium">Medium</option>
  <option value="high">High</option>
</select>

What I need to do to have selected priority from database?



Solution 1:[1]

I think you need to change your template slightly:

<div>
  <%= form.label :priority %>
  <%= form.select :priority, [["No priority", "No priority"], ["Low", "Low"], ["Medium", "Medium"], ["High", "High"]] %>
</div>

Why: Since priority is overridden as super.to_s.humanize, the value that the form helper gets is the humanized form rather than the enum key form.

If you want to get at the raw value for your enum, you can call the pluralized name of the enum as a method on the class, e.g. Project.priorities. This will return the hash that the enum was defined as.

Further suggestion: I think that overriding the attribute methods from ActiveRecord is not worth the trouble it causes. The priority value is an attribute of the model (the data layer) while the humanized string really belongs on the view layer. I would suggest defining a new method called humanized_priority on Project to start off with, but you can take the separation of concerns further by extracting the method out into a view helper or using presenters.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Pawan