2013-07-31 2 views
0

У меня есть контроллер Rails, который имеет 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 
+1

Как насчет 'before_filter: set_common_variables'? –

+0

Я бы поместил это в application_controller или как частный метод? – rigelstpierre

+1

Приватный метод на этом контроллере –

ответ

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. Точно так же вы можете реорганизовать свой второй метод. Любая модель бизнес-логики и обработка данных должны обрабатываться в моделях

Кроме того, я вижу, что в контроллере слишком много неиспользуемых локальных переменных. Контроллер должен быть как можно более тонким.

+1

+1, каждая обработка должна перейти к модели, чтобы ее можно было разделить между контроллерами. Модели и тонкие контроллеры +1 –

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 

примечания: не ставить код расчета в поле зрения, это медленно

1

Если вы решили сохранить его в контроллере, то попробуйте следующее:

 
class ChartsController < ApplicationController 

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

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

    @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 
    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 

    private 

    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' }) 
    end 

end 

Переменная экземпляра @freight_details будет доступна в обоих методах. Before_filter выполнит метод load_data только для этих двух методов.

Удачи!

Смежные вопросы