Search on second order association - activescaffold/active_scaffold GitHub Wiki
Let’s suppose a models relationship as follows:
class Employee < ActiveRecord::Base
has_many :jobs
has_many :tasks, :through => :jobs
end
class Job < ActiveRecord::Base
belongs_to: employee
has_many :tasks
end
class Task < ActiveRecord::Base
belongs_to: job
endA common need is displaying the ‘employee’ associated to each ‘task’ in the ‘tasks’ list view, and also allowing search based on ‘employee’. Following code implements it.
First of all define a ‘employee’ field for ‘task’ model (note that there could be no ‘job’ associated to current ‘task’ model, or no ‘employee’ associated to its ‘job’):
class Task < ActiveRecord::Base
[...]
delegate :employee, :to => :job, :allow_nil => trueAdd the required “magic” to ‘tasks’ controller:
- Add ‘employee’ to the columns, and exclude it so you don’t want it in other actions.
- Add ‘employee’ to the search fields.
- Set the table/column or SQL for the ‘employee’ search.
- Set an include in ‘job’ field.
class TasksController < ApplicationController
active_scaffold do |config|
config.columns << :employee
config.columns.exclude :employee
[...]
config.search.columns << :employee
config.columns[:employee].search_sql = "employees.name"
config.columns[:employee].includes = {:job => :employee}
config.columns[:employee].search_ui = :string # optional
config.columns[:employee].options[:string_comparators] = true # optional
end
endThe SQL added during a ‘employee’ search by the above code looks as follows:
[...] LEFT OUTER JOIN `employees` ON `employees`.id = `jobs_tasks`.employee_id WHERE (((LOWER(employees.name) LIKE '%[...]%')))And voilá, the ‘tasks’ list view displays the ‘employee’ for each row and also allows search based on its name.