Rails Select: When Pre-existing Record is not in Select

139 views Asked by At

I'm wondering the best way to deal with this issue. On my site I have several select boxes where users can associate employees to records. These select boxes are filtered to only show active employees though. So a problem arises when we change an employee to inactive, then try to edit a record.

Say we create an Invoice for Mary Jane and she is an active employee. Great.

Then we disable Mary Jane as an employee. Cool.

Later on we go back and edit the Invoice and add some notes or something--well now since Mary Jane is inactive, she doesn't show up as an option in the select list. So, when the invoice is saved, the "blank" option is selected and she is removed from the invoice. Even though she's now inactive, I don't want to delete her off the invoice record.

I'm trying to find the most elegant way to do this--I could try using a before_save validation I suppose, or maybe I could create a scope that includes all active employees plus somehow figures out if the current record has an inactive employee and includes it? I'm just not sure the best way to go about this. Anyone run into this issue?

1

There are 1 answers

0
FireDragon On

I will answer how I resolved this using scopes since other users have requested this. Continuing with the example above, let's say we have Invoice and Employee models:

class Invoice < ActiveRecord::Base
  belongs_to :employee
end

class Employee < ActiveRecord::Base
  has_many :invoices

  # the select_menu scope takes an employee instance as an argument
  # and adds this employee to the list of 'active' employees
  scope :active, where(active: true)
  scope :select_menu, lambda { |another_employee| active << another_employee }
end

Then, in your view/form, use the select_menu scope and pass in the current (inactive) employee to add them to the drop-down list:

/views/invoices/_form.html.erb

<%= simple_form_for @invoice do |f| %>
  <%= f.association :employee, collection: Employee.select_menu(@invoice.employee).sort_by(&:name), label_method: :first_last, include_blank: "" %>
  ...
<% end %>

So, assuming this form is used normally in the new and edit views--when the new action is called, there isn't an employee linked and only active employees are shown in the drop-down. When the edit action is called, the @invoice has a (possibly inactive) employee, and this employee will be added to the list of active employees using the scope.

If anyone has a better idea of how to do this, I'm all ears, but this was the cleanest solution I found so far.