I’m working on some search functionality which, depending on parameters sent with the search form, will search different section of a site. This search logic has gotten quite hairy, and I’m looking into different ways of attacking a refactoring.
My current angle is to extract all the slightly hairy logic from the controller into a form object.
In the form object different views can be rendered depending on values in the params hash, and I’m thinking keeping this logic inside the form object could be nice, but I’m not sure about actually performing the rendering there.
My question is thus: What’s your opinion on rendering templates in the form object?
I would say the form object shouldn’t be responsible for rendering the response. It should pass back a collection of search results, and the controller can render the appropriate template.
You could encapsulate the results in a object, and have a field which indicates the variant of result, and use this to decide which view to render, e.g.:
class SearchController < ApplicationController
def index
results = SearchForm.new(params[:query]).results
template_filename = results.variant
render template_filename, collection: results.records
end
end
After looking at this for a while I was drawn to the same conclusion. I’ve currently refactored it so that the form returns two objects. One that is a presenter representing the entire search (wrapping the query, results etc) + a hash containing values to be passed the the renderer.
So I’ve ended with something like this:
class SearchController < ApplicationController
def index
search_presenter, view_variables = SearchForm.new(params).results
if search_presenter && view_variables
render search_presenter.view_name, locals: view_variables
else
raise "Unable to perform search. Params: #{params}"
end
end
end