Search code examples
ruby-on-railssimple-formmodel-associations

Rails: Simple Form Association label_method from Grandparent


I am trying to build a form that will create a new record using Simple Form, but I am having trouble showing the correct label in the dropdown list. First, the relevant models:

class Service < ActiveRecord::Base
  belongs_to :business
  has_one :enrollment
  has_many :clients, through: :enrollment
end

class Client < ActiveRecord::Base
  belongs_to :business
  has_one :enrollment
  has_many :services, through: :enrollment
end

class Enrollment < ActiveRecord::Base
  belongs_to :service
  belongs_to :client
  has_many :jobs
end

class Job < ActiveRecord::Base
  belongs_to :enrollment
end

The basic idea is that a client will be enrolled in one or more services. A job represents an appointment to perform the service. When creating a new job, I need to select the enrollment that the job belongs to. From the html.erb:

<%= f.association :enrollment, label_method: :service_id, value_method: :id, prompt: 'Choose an enrolled service' %>

This sort of works, but it only shows me the service_id from the Enrollment table. What I want to see is the name of the Client (fname and lname) and the name of the Service concatenated in the dropdown list, like this: "John Doe: Window Washing". The problem is that both of those come from the parents of Enrollments. Basically I need to traverse two associations to get to the label that I want.

I thought about de-normalizing so that the Enrollment record has the data I need, but I'd rather not do that.

Any ideas?


Solution

  • In the Enrollment class define following method:

    def name
      "#{client.full_name}: #{service.name}"
    end
    

    Then you should be able to use this method in your form:

    <%= f.association :enrollment, label_method: :name, value_method: :id, prompt: 'Choose an enrolled service' %>
    

    To avoid 2*n+1 sql queries prepare enrollments collection with included clients and services.