2010-09-28 22 views
1

我有一個控制器有兩個不同的動作,但都需要這個相同的代碼,這是有點長,我怎麼能讓他們訪問這個相同的行爲,但保持乾爽?相同的代碼在控制器在軌道的不同動作 - 如何使DRY?

@list = Contact.find :all, 
     :select => "companies.name AS co_name, 
        companies.id AS comp_id, 
        COUNT(contact_emails.id) AS email_count, 
        COUNT(contact_calls.id) AS call_count, 
        COUNT(contact_letters.id) AS letter_count, 
        COUNT(contact_postalcards.id) AS postalcard_count", 

     :conditions => ['contact_emails.date_sent < ? and contact_emails.date_sent > ?', 
         report_end_date, report_start_date], 

     :joins => [ 
     "LEFT JOIN companies ON companies.id = contacts.company_id", 
     "LEFT JOIN contact_emails ON contact_emails.contact_id = contacts.id", 
     "LEFT JOIN contact_letters ON contact_letters.contact_id = contacts.id", 
     "LEFT JOIN contact_postalcards ON contact_postalcards.contact_id = contacts.id", 
     "LEFT JOIN contact_calls ON contact_calls.contact_id = contacts.id" 
     ], 
     #:group => "companies.id" 
     :group => "companies.name" 
    puts @list[0].attributes.inspect 
+0

這不回答你的問題,但我90%確定所有這些「連接」都可以替換爲「包含」。就像這樣::include => [:公司,:contact_emails,:contact_letters,:contact_postalcards,:contact_calls]。 – Brad 2010-09-29 15:28:09

回答

8

您應該將此代碼移到模型:

# Contatct model 

def self.get_list(report_start_date, report_end_date) 
    self.find :all, 
    :select => "companies.name AS co_name, 
       companies.id AS comp_id, 
       COUNT(contact_emails.id) AS email_count, 
       COUNT(contact_calls.id) AS call_count, 
       COUNT(contact_letters.id) AS letter_count, 
       COUNT(contact_postalcards.id) AS postalcard_count", 

    :conditions => ['contact_emails.date_sent < ? and contact_emails.date_sent > ?', 
        report_end_date, report_start_date], 

    :joins => [ 
     "LEFT JOIN companies ON companies.id = contacts.company_id", 
     "LEFT JOIN contact_emails ON contact_emails.contact_id = contacts.id", 
     "LEFT JOIN contact_letters ON contact_letters.contact_id = contacts.id", 
     "LEFT JOIN contact_postalcards ON contact_postalcards.contact_id = contacts.id", 
     "LEFT JOIN contact_calls ON contact_calls.contact_id = contacts.id" 
    ], 
    #:group => "companies.id" 
    :group => "companies.name" 
end 

然後你就可以在控制器上使用它:

@list = Contact.get_list(report_start_date, report_end_date) 

也許你也可以把它拆分爲較小的部分,並使用範圍和定義的關聯,而不是自己編寫所有的關聯。

+0

絕對是。此代碼尖叫,「讓我離開控制器!」將它推入模型將清理代碼,並允許您從rake任務中訪問該方法,或者如果您希望爲該一次性報告提取該列表,則可以更容易地從控制檯訪問該方法。 – jdl 2010-09-28 21:35:59

+0

這段代碼的樣子吧,我很想把它清理乾淨,但我無法找到一個方法.... – Angela 2010-09-29 03:14:09

+0

加入通常是醜陋的,重要的事情是,它是幹:你只需要一次定義它在模型中,但你可以多次調用各種控制器,正如klew指出的那樣。 – 2010-10-01 01:02:50

1

我想補充一個函數生成數和連接SQL:

class Contact < ActiveRecord::Base 
    def self.get_list(report_start_date, report_end_date) 
    all(:select  => "companies.name AS co_name, 
         companies.id AS comp_id, 
         #{table_count_col(
          :contact_emails, 
          :contact_calls, 
          :contact_letters, 
          :contact_postalcards 
         )}", 
     :conditions => ['contact_emails.date_sent < ? AND 
         contact_emails.date_sent > ?', 
         report_end_date, report_start_date], 
     :joins  => join_table(
        :companies, 
        :contact_emails, 
        :contact_letters, 
        :contact_postalcards, 
        :contact_calls 
        ), 
     ) 
    end 
end 

table_count_coltable_join都在裏面Contact類的靜態方法:

def self.table_count_col(*args)  
    args.collect do |table| 
     count_col = "#{table.to_s.gsub(/^contact_/, '').singularize}_count" 
     "COUNT(#{table}.id) AS #{count_col}"  
    end.join(",") 
    end 

    def self.table_join(*args)  
    args.collect do |table| 
    "LEFT JOIN #{table} ON #{table}.id = contacts.company_id" 
    end.join(",") 
    end  
+0

table_count_col是一個方法上的聯繫人是table_join? – Angela 2010-09-29 03:15:20

+0

是的,它們是Contact類的靜態方法。 – 2010-09-29 06:44:31

+0

我喜歡+1幫助簡化 - 可能需要分階段實施 – Angela 2010-09-29 16:20:43

相關問題