0

我有一个具有 2 种方法的 Rails 控制器。两种方法都使用一些相同的变量,我想知道如何将其重构为控制器某处的模型中的任何一种方法,以使它们比现在更可重用。

class ChartsController < ApplicationController

  before_filter :authenticate_user!, :company_id

  def service_level
    latest_date = Invoice.where(:account_id => @company.accounts).maximum(:invc_date)
    invoices_filter = { :invoices => { :invc_date => (latest_date - 3.months)..latest_date } }

    invoices = Invoice.where({:account_id => @company.accounts}.merge(invoices_filter))
    details = InvoiceDetail.joins(:type).where(:invoice_id => invoices)
    freight_details = details.where(:invoice_detail_types => { :category => 'freight' })

    freight_groups = freight_details.group(:family).select("family, count(distinct package_id), sum(base_charge + discount)")


    vol_data = {}
    spend_data = {}

    @charts = {}

     @charts[:service_analysis] = {
      :vol_data => Hash[freight_groups.map { |row| [InvoiceDetailFamily[row.family].name, row.count.to_i] }],
      :spend_data => Hash[freight_groups.map { |row| [InvoiceDetailFamily[row.family].name, row.sum.to_f] }]
    }

    render partial: 'service_level'
  end

  def weight_summary

    latest_date = Invoice.where(:account_id => @company.accounts).maximum(:invc_date)
    invoices_filter = { :invoices => { :invc_date => (latest_date - 3.months)..latest_date } }

    invoices = Invoice.where({:account_id => @company.accounts}.merge(invoices_filter))
    details = InvoiceDetail.joins(:type).where(:invoice_id => invoices)
    freight_details = details.where(:invoice_detail_types => { :category => 'freight' })
    packages = freight_details.joins(:package, :invoice)



    vol_data = {}
    spend_data = {}
    packages.group(:zone).select("zone, count(distinct package_id), sum(base_charge + discount)").each do |row|
      case row.zone
        when '02'..'08', '002'..'008', '102'..'108', '132'..'138', '202'..'208', '242'..'248', '302'..'308'
          zg = row.zone[-1]
        when '09'..'17', '124'..'126', '224'..'226'
          zg = 'AK/HI/PR'
        else
          zg = 'Import/Export'
      end
      vol_data[zg] = (vol_data[zg] || 0) + row.count.to_i
      spend_data[zg] = (spend_data[zg] || 0) + row.sum.to_f
    end
    @charts = {}

    @charts[:weight_analysis] = {
      :vol_data => Hash[(vol_data.sort_by {|key, value| key.scan(/\d+/)[0].to_i})],
      :spend_data => Hash[(spend_data.sort_by {|key, value| key.scan(/\d+/)[0].to_i})]
    }


    render partial: 'weight_summary'
  end
end
4

3 回答 3

3

我建议使用模型类方法来处理数据。例如

freight_details = details.where(:invoice_detail_types => { :category => 'freight' })

freight_groups = freight_details.group(:family).select("family, count(distinct package_id), sum(base_charge + discount)")


vol_data = {}
spend_data = {}

@charts = {}

 @charts[:service_analysis] = {
  :vol_data => Hash[freight_groups.map { |row| [InvoiceDetailFamily[row.family].name, row.count.to_i] }],
  :spend_data => Hash[freight_groups.map { |row| [InvoiceDetailFamily[row.family].name, row.sum.to_f] }]
}

可以移动到返回的模型类方法charts。以同样的方式,您可以重构您的第二种方法。任何类型的业务逻辑和数据处理都应该在模型中处理

此外,我可以看到控制器中有太多未使用的局部变量。控制器应尽可能薄。

于 2013-07-31T22:28:19.037 回答
1

使用装饰器之类的概念

module Chart
   extend self
   def service_analysis(freight_groups, freight_groups)

   end
end
class ChartsController < ApplicationController
    @chart = Chart.service_analysis(freight_groups, freight_groups)
end

注意:不要将计算代码放在视图中,它很慢

于 2013-08-01T00:03:42.127 回答
1

如果您决定将其保留在控制器中,请尝试以下操作:

类 ChartsController < ApplicationController

  before_filter :authenticate_user!, :company_id
  before_filter :load_data, :only => [:service_level, weight_summary]

  定义服务级别
    Freight_groups = @freight_details.group(:family).select("family, count(distinct package_id), sum(base_charge + discount)")

    @charts = {}
    @charts[:service_analysis] = {
      :vol_data => 哈希[freight_groups.map { |row| [InvoiceDetailFamily[row.family].name, row.count.to_i] }],
      :spend_data => 哈希[freight_groups.map { |row| [InvoiceDetailFamily[row.family].name, row.sum.to_f] }]
    }

    渲染部分:'service_level'
  结尾

  def weight_summary
    包裹 = @freight_details.joins(:package, :invoice)

    vol_data = {}
    花费数据 = {}

    packages.group(:zone).select("zone, count(distinct package_id), sum(base_charge + discount)").each do |row|
      案例行区
        当'02'..'08','002'..'008','102'..'108','132'..'138','202'..'208','242'。 .'248'、'302'..'308'
          zg = row.zone[-1]
        当'09'..'17','124'..'126','224'..'226'
          zg = 'AK/HI/PR'
        别的
          zg = '导入/导出'
      结尾
      vol_data[zg] = (vol_data[zg] || 0) + row.count.to_i
      花费数据[zg] = (花费数据[zg] || 0) + row.sum.to_f
    结尾
    @charts = {}

    @charts[:weight_analysis] = {
      :vol_data => Hash[(vol_data.sort_by {|key, value| key.scan(/\d+/)[0].to_i})],
      :spend_data => Hash[(spend_data.sort_by {|key, value| key.scan(/\d+/)[0].to_i})]
    }

    渲染部分:'weight_summary'
  结尾

  私人的

  def load_data
    latest_date = Invoice.where(:account_id => @company.accounts).maximum(:invc_date)
    invoices_filter = { :invoices => { :invc_date => (latest_date - 3.months)..latest_date } }
    invoices = Invoice.where({:account_id => @company.accounts}.merge(invoices_filter))
    details = InvoiceDetail.joins(:type).where(:invoice_id => invoices)
    @freight_details = details.where(:invoice_detail_types => { :category => 'freight' })
  结尾

结尾

实例变量@freight_details 在这两种方法中都可用。before_filter 只会对这两种方法执行 load_data 方法。

祝你好运!

于 2013-08-01T10:23:56.000 回答