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。同じ方法で、2 番目のメソッドをリファクタリングできます。あらゆる種類のビジネス ロジックとデータ処理は、モデルで処理する必要があります。

さらに、コントローラーには未使用のローカル変数が多すぎることがわかります。コントローラーはできるだけ薄くする必要があります。

于 2013-07-31T22:28:19.037 に答える
1

コントローラー内に保持することにした場合は、これを試してください。

class ChartsController < ApplicationController

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

  def service_level
    cargo_groups = @freight_details.group(:family).select("family, count(distinct package_id), sum(base_charge + discount)")

    @チャート = {}
    @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] }]
    }

    部分的にレンダリング: 'service_level'
  終わり

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

    vol_data = {}
    支出データ = {}

    packages.group(:zone).select("zone, count(distinct package_id), sum(base_charge + discount)").each do |行|
      ケース行.ゾーン
        '02'..'08'、'002'..'008'、'102'..'108'、'132'..'138'、'202'..'208'、'242' の場合。 .'248', '302'..'308'
          zg = 行.ゾーン[-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[: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 } }
    請求書 = Invoice.where({:account_id => @company.accounts}.merge(invoices_filter))
    details = InvoiceDetail.joins(:type).where(:invoice_id => 請求書)
    @freight_details = details.where(:invoice_detail_types => { :category => 'freight' })
  終わり

終わり

インスタンス変数 @freight_details は、両方の方法で利用できます。before_filter は、これら 2 つのメソッドに対してのみ load_data メソッドを実行します。

幸運を!

于 2013-08-01T10:23:56.000 に答える
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 に答える