Re: This tweet
Inlining, collection partials, helpers, or builder objects. Partials shouldn't be the only tool in your belt for reducing duplicated view code.
Depends on the situation.
With ActiveRecord it is easy to load the same object multiple times, especially when the same objects are being used in various places in the view, possibly filtered or grouped differently. I was able to cut my benchmark times in half by writing some helper classes that memoize a collection of AR objects and then expose methods to filter / group them as needed in the view. Here's a simplistic example:
# Original view
- assignment_types.each do |assignment_type|
- assignment_type.assignments.each do |assignment|
# My proposed solution:
class CourseData
def initialize(course)
@course = course
end
def assignment_types
@assignment_types ||= @course.assignment_types
end
def assignments_for_assignment_type(assignment_type)
assignments_by_assignment_type_id[assignment_type.id]
end
private
def assignments
@assignments ||= @course.assignments
end
def assignments_by_assignment_type_id
@assignments_by_assignment_type_id ||= assignments.group_by(&:assignment_type_id)
end
end
- current_course_data.assignment_types.each do |assignment_type|
- current_course_data.assignments_for_assignment_type(assignment_type).each do |assignment|
I ended up writing a few of these to optimize for different use cases (e.g. a professor generally looks at data for all students in a course, whereas a student generally looks at their own data).
If the problem is too many AR objects being loaded, but not many duplicates, then I think the solution is to rely on the database more. In simple cases, pluck
can be used to get a few values directly. We've been using Postgres views to calculate cache keys, aggregate data, and perform complex filtering that was too unwieldy in a scope or class method.