Cómo refactorizar el código Ruby (controlador)?
-
09-09-2019 - |
Pregunta
Este es el código en mi controlador de informes, que sólo se ve tan mal, alguien me puede dar algunas sugerencias sobre cómo ordenarlo?
# app\controller\reports_controller.rb
@report_lines = []
@sum_wp, @sum_projcted_wp, @sum_il, @sum_projcted_il, @sum_li,@sum_gross_profit ,@sum_opportunities = [0,0,0,0,0,0,0]
date = @start_date
num_of_months.times do
wp,projected_wp, invoice_line,projected_il,line_item, opp = Report.data_of_invoicing_and_delivery_report(@part_or_service,date)
@sum_wp += wp
@sum_projcted_wp +=projected_wp
@sum_il=invoice_line
@sum_projcted_il +=projected_il
@sum_li += line_item
gross_profit = invoice_line - line_item
@sum_gross_profit += gross_profit
@sum_opportunities += opp
@report_lines << [date.strftime("%m/%Y"),wp,projected_wp ,invoice_line,projected_il,line_item,gross_profit,opp]
date = date.next_month
end
Busco a utilizar algún método como
@sum_a,@sum_b,@sum_c += [1,2,3]
Solución
Mi pensamiento inmediato es: mover el código a un modelo
.El objetivo debe ser "Controladores delgado", por lo que no debe contener la lógica de negocio.
En segundo lugar, me gustaría presentar mis líneas del informe de mis puntos de vista como OpenStruct () objetos, lo que parece más limpio para mí.
Así que me gustaría considerar mover esta lógica de acumulación en (lo más probable) un método de clase de Informe y devuelve una matriz de OpenStructs "línea de informe" y una única totales OpenStruct pasar a mi punto de vista.
Mi código del controlador se convertiría en algo como esto:
@report_lines, @report_totals = Report.summarised_data_of_inv_and_dlvry_rpt(@part_or_service, @start_date, num_of_months)
EDIT: (A días más tarde)
En cuanto a que la adición de acumulación cosa-en-una-matriz, se me ocurrió esto:
require 'test/unit'
class Array
def add_corresponding(other)
each_index { |i| self[i] += other[i] }
end
end
class TestProblem < Test::Unit::TestCase
def test_add_corresponding
a = [1,2,3,4,5]
assert_equal [3,5,8,11,16], a.add_corresponding([2,3,5,7,11])
assert_equal [2,3,6,8,10], a.add_corresponding([-1,-2,-2,-3,-6])
end
end
Look: una prueba! Parece funcionar bien. No hay ninguna comprobación de las diferencias de tamaño entre las dos matrices, así que hay un montón de maneras que podría salir mal, pero el concepto parece sonar suficiente. Estoy pensando en probar algo similar que me permitiera tomar un conjunto de resultados ActiveRecord y acumularlo en un OpenStruct, que es lo que suelo usar en mis informes ...
Nuestro nuevo método de matriz podría reducir el código original a algo como esto:
totals = [0,0,0,0,0,0,0]
date = @start_date
num_of_months.times do
wp, projected_wp, invoice_line, projected_il, line_item, opp = Report.data_of_invoicing_and_delivery_report(@part_or_service,date)
totals.add_corresponding [wp, projected_wp, invoice_line, projected_il, line_item, opp, invoice_line - line_item]
@report_lines << [date.strftime("%m/%Y"),wp,projected_wp ,invoice_line,projected_il,line_item,gross_profit,opp]
date = date.next_month
end
@sum_wp, @sum_projcted_wp, @sum_il, @sum_projcted_il, @sum_li, @sum_opportunities, @sum_gross_profit = totals
... lo que si el informe # data_of_invoicing_and_delivery_report también podría calcular gross_profit
reduciría aún más a:
num_of_months.times do
totals.add_corresponding(Report.data_of_invoicing_and_delivery_report(@part_or_service,date))
end
completamente no probado, pero eso es un infierno de una reducción por la adición de un método de una línea para la matriz y la realización de un solo resta extra en un modelo.
Otros consejos
Crea un objeto de la suma que contiene todos esos campos, pasar toda la matriz a @ sum.increment_sums (Report.data_of ...)