Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I use lookup_context to make this view as DRY as possible?

For starters, this is the view I am trying to replicate:

screenshot of grades layout

This is the HTML from that layout (from the SAT portion anyway, you can extrapolate the rest):

<table class="table table-hover table-bordered">
                        <thead>
                        <td colspan="2" class="text-center">
                          <strong>SAT</strong>
                        </td>
                        <tr>
                            <th>Subject</th>
                            <th>Grade</th>
                        </tr>
                        </thead>
                        <tbody>
                        <tr>
                            <td>Reading</td>
                            <td>900</td>
                        </tr>
                        <tr>
                            <td>Math</td>
                            <td>700</td>
                        </tr>
                        <tr>
                            <td>Writing</td>
                            <td>800</td>
                        </tr>
                        <tr>
                            <td><strong>Total</strong></td>
                            <td><strong>2,400</strong></td>
                        </tr>
                        </tbody>

This is what my Grade.rb model looks like:

# == Schema Information
#
# Table name: grades
#
#  id         :integer          not null, primary key
#  subject    :string
#  result     :string
#  grade_type :integer
#  profile_id :integer
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

class Grade < ActiveRecord::Base
  belongs_to :profile

  enum grade_type: { csec: 0, cape: 1, sat: 2, g7: 3, g8: 4, g9: 5, g10: 6, g11: 7, g12: 8, g13: 9 }
end

This is what that table looks like currently, i.e. before using the lookup_context method in Rails:

<table class="table table-hover table-bordered">
                    <thead>
                    <td colspan="2" class="text-center">
                      <strong>SAT</strong>
                    </td>
                    <tr>
                        <th>Subject</th>
                        <th>Grade</th>
                    </tr>
                    </thead>
                    <tbody>
                      <% @sat_grades.each do |grade| %>
                      <tr>
                        <% if grade.subject.eql? "Total" %>
                          <td><strong><%= grade.subject %></strong></td>
                          <td><strong><%= grade.result %></strong></td>
                        <% else %>
                          <td><%= grade.subject %></td>
                          <td><%= grade.result %></td>
                        <% end %>
                      </tr>
                      <% end %>
                    </tbody>

Where @sat_grades is this: @sat_grades = @profile.grades.where(grade_type: :sat).

I want to use this lookup_context method, I was thinking like this:

 <% @grades.each do |grade| %>
   <% if lookup_context.template_exists?(grade.grade_type, "grades/grade_types", true) %>
       <%= render partial: "grade/grade_types/#{grade.grade_type}", locals: {event: event, index: index} %>
   <% end %>
  <% end %>

The issue I am running into is that each grade_type has a different table. So grade_type: :sat belongs in the "SAT" table, the same for "CSEC", "g11", etc.

I can't think of a way to have each of those grade_types rendered specifically within their HTML table, without having lots of lookup_context.template_exists? calls within that view.

It almost defeats the purpose of doing it like that, if I have to have a lookup_context call for each grade_type.

What's the best way to approach this so I just have 1 lookup_context call (if possible), but it correctly renders and handles all the different grades correctly.

like image 929
marcamillion Avatar asked Sep 17 '16 12:09

marcamillion


1 Answers

With the given fragment I would try the following:

# Render each grade
<%= render(partial: "grade/grade", collection: @grades, locals: {event: event, index: index}) || "There's grade to be displayed" %>
# Render Concated content
<%= content_for :all_grades %>

Within grade/_grade.html.erb:

 # If a special grade template exists prepare the content to be shown
 # but don't display it right now
 <% if lookup_context.template_exists?(grade.grade_type, "grades/grade_types", true) %>
   <%= render partial: "grade/grade_types/#{grade.grade_type}", locals: {event: event, index: index} %>
 <% end %>

  # Render the common stuff
  ...
  # Display the special stuff stored for the grade
    <%= content_for :grade_table %>
  # Repeat previous steps
  ...

Within the grade template (for instance grade/grade_types/_g7.html.erb):

# remove content from previous grades
<% content_for :grade_table,  flush: true do %>
   ...
<% end %>

<% content_for :xxx_xxx,  flush: true do %>
   ...
<% end %>
...

# Concat content for all grades together (flush: false)
<% content_for :all_grades do %>
  ...
<% end %>

Another approach can be a presenter or maybe even Single Table Inheritance.

like image 160
slowjack2k Avatar answered Oct 24 '22 07:10

slowjack2k