Extract list of selected contractors by matching serialized array in Rails

Posted on

Problem

I’m working on an application where I have a Company model setup as follows:

class Company < ActiveRecord::Base
  has_many :employee_roles
  has_many :employees
  validates :company_name, uniqueness: true
  serialize :contractors, Array

end

Contractors is related to the company as a serialized array and saves the data in the db as ["2", "1"] where 2 and 1 are the id’s of the contractors.

My code to extract the list of selected contractors from this is:

def coach_list
  @contractors = Contractor.where({ verified: true,
                        validated: true })
              .where('membership_type != ?', Contractor.membership_types["no_membership"])
  @company = Company.find(contractor_company_params[:company_id])
  @selected_contractors = @company.contractors.map { |c| Contractor.find(c.to_i) }
  @unselected_contractors = @contractors - @selected_contractors
end

I’m not sure if this is the best way to extracted @selected_contractors and @unselected_contractors

Solution

If your database supports array types natively I would use that feature, I know that Postgres does. I would also call the field contractor_ids or even selected_contractor_ids then use a method called contractors or selected_contractors to return the actual objects.

I would change this:

@contractors = Contractor.where({ verified: true, validated: true })
                         .where('membership_type != ?', Contractor.membership_types["no_membership"])

to a scope or scopes on the Contractor class. You can also code the second where clause as where.not(membership_type: Contractor.membership_types["no_membership"])

And I would change this:

@selected_contractors = @company.contractors.map { |c| Contractor.find(c.to_i) }

to be a method on the Company class. I would also write it as:

@selected_contractors = Contractor.find(@company.contractors) 

this would issue a single query instead of n queries, additionally the to_i is not usually necessary.

Leave a Reply

Your email address will not be published. Required fields are marked *