2010-09-28 5 views
1

J'ai un contrôleur avec deux actions différentes, mais les deux ont besoin de ce même code, qui est un peu long, comment puis-je leur permettre d'accéder à ce même comportement mais le garder au sec?même code dans les différentes actions du contrôleur dans les rails - comment faire 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

Ce ne répond pas à votre question, mais Je suis sûr à 90% que toutes ces "jointures" pourraient être remplacées par "includes". Quelque chose comme ceci:: include => [: entreprises,: contact_emails,: contact_letters,: contact_postalcards,: contact_calls]. – Brad

Répondre

8

Vous devez déplacer ce code pour le modèle:

# 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 

Ensuite, vous pouvez l'utiliser dans les contrôleurs:

@list = Contact.get_list(report_start_date, report_end_date) 

vous pouvez probablement aussi diviser de parties plus petites et les champs d'utilisation et associations définies au lieu de tout écrire par vous-même.

+0

Très certainement. Ce code crie: «Sors-moi du contrôleur! Le pousser vers le modèle nettoie votre code, et vous permet d'accéder à la méthode à partir d'une tâche de rake ou plus facilement depuis la console si vous souhaitez afficher cette liste pour un rapport unique. – jdl

+0

ce code a l'air bien, j'aimerais le nettoyer, mais je ne pouvais pas trouver un moyen .... – Angela

+0

Les jointures sont généralement moche, les choses importantes est qu'il est sec: il suffit de le définir une fois dans le modèle, mais vous pouvez l'appeler plusieurs fois est différents contrôleurs, comme l'a souligné klew. –

1

J'ajouterais une fonction pour générer le nombre et rejoindre 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_col et table_join sont des méthodes statiques à l'intérieur Contact classe:

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 est une méthode sur Contacts, tout comme table_join? – Angela

+0

Oui, ce sont des méthodes statiques sur la classe Contact. –

+0

J'aime +1 pour aider à simplifier - peut-être mettre en œuvre en plusieurs phases – Angela

Questions connexes