Как извлечь «таблицу» из массива ActiveRecords в Rails?

У меня есть несколько похожих моделей (ContactEmail, ContactLetter, ContactPostalcard).

Каждый экземпляр (запись), скажем, в ContactEmail, означает, что конкретный шаблон электронной почты был отправлен конкретному контакту.

Итак, каждый (например, ContactEmail) assign_to: contact

Итак, в модели ContactEmail есть атрибут ContactEmail.contact_id .

Каждый контакт имеет виртуальный атрибут company_name.

Итак, когда я напишу следующее, я получу все электронные письма, отправленные в пределах определенного набора условий (в данном случае, времени):

@sent_emails = ContactEmail.find(:all, :conditions => "conditions here")

Итак, @ sent_emails.size сообщит мне общее количество из всех отправленных писем.

Моя задача: как извлечь больше детализации, уникальной компанией в разных моделях?

Вывод, который я хочу, выглядел бы следующим образом:

FROM 8/1/10 TO 8/10/10 (where the dates are dynamic)

                Calls       Letter      Postalcards
Company 1         4           2             4
Company 2        10           4             6
Company 3         2           3             4

Таким образом, Company3 имеет 2 Calls, что означает, что было две записи ContactCalls, где sent_date упал между двумя датами, и где связанный контакт принадлежит Компании 3.

Компания 1-3 не установлена ​​заранее. Его нужно извлечь из пула ContactCalls, ContactLetters и ContactPostalcards .....

Проблема в том, что я не знаю, что это за компании. Они являются атрибутами части контактов каждой отдельной записи. Так что в некоторых случаях у меня может быть Company2 имеет 0 букв.

Спасибо за любое руководство! :)

Как найти компанию по заданной записи для модели ContactEmail:

ContactEmail.contact.company.name

Это вернет ассоциированную компанию для определенного ContactEmail

7
задан Timothy T. 20 August 2010 в 23:22
поделиться

4 ответа

Это должно быть хорошо:

    list = Contact.find :all,
      :select => "companies.name company_name, COUNT(contact_emails.id) email_count, COUNT(contact_letters.id) letter_count, COUNT(contact_postalcards.id) postalcard_count",
      :joins => [
        "LEFT JOIN companies ON company.id = contact.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"
      ],
      :group => "companies.id"

      list.each do |item|
        p item.company_name, item.email_count, item.letter_count, item.postalcard_count
      end
2
ответ дан 7 December 2019 в 18:38
поделиться

На мой взгляд, попытка извлечь эти данные в одном запросе (что, я полагаю, вы и хотите сделать) - это немного перебор. Я бы выдал по одному запросу для каждого типа с опцией :group => company_name. Затем я бы объединил результаты с помощью кода Ruby, чтобы получить некоторую структуру данных, позволяющую легко отображать их (вероятно, хэш хэшей, например, {'Company 1' => {'Calls' => 5, 'Letter' => 0, 'Postalcards' => 3'}...}.

0
ответ дан 7 December 2019 в 18:38
поделиться

Если вы действительно хотите иметь все контакты с подсчетом всех этих отношений, было бы неплохо использовать counter_cache.

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html - найти кеш счетчика на этой странице

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

Что вам нужно сделать, так это добавить столбцы «emails_count», «letter_count» и «postcards_count» в таблицу «контактов», сначала обновить ее, указав правильное количество, и объявить ваши отношения has_many как таковые:

class Contact < ActiveRecord::Base
  has_many :emails, :class_name => 'ContactEmail', :counter_cache => 'emails_count'
  # so on for other columns
end

С помощью этих При настройке все, что вам нужно сделать, это запросить ваши контакты и проверить их кеш счетчиков, чтобы отобразить вашу таблицу. Его номер будет автоматически обновляться рельсами каждый раз, когда для этого контакта создается или уничтожается элемент.

0
ответ дан 7 December 2019 в 18:38
поделиться

О, значит, я сначала неправильно понял ваш вопрос. Думаю, я наконец понял, что ты имеешь в виду.

Итак, действительно, единственный хороший способ сделать то, что вы хотите (вытащить все данные из всех этих таблиц), - это запустить include при запросе контактов:

@contacts = Contact.all :include => [:contact_emails, :contact_letters, :contact_postal_cards]

Это сгенерирует 4 запроса, выбрав все данные на Эти 4 таблицы заполняют ваши контакты соответствующим образом, поэтому вы можете перемещаться по отношениям контактного объекта любым способом, которым вам нравится заполнять свою таблицу.

Наконец, вы упомянули, что ваша таблица будет сгруппирована по компаниям, а не по контактам, поэтому я предполагаю, что у нескольких контактов может быть одно и то же 'company_name'.В этом случае вы можете сгруппировать свою коллекцию по 'company_name' следующим образом

@companies = @contacts.group_by &:company_name

Это создаст такой хеш:

{'Company 1' => [contact_1, contact_3], 'Company 2' => [contact_4]}

С их помощью вы можете сгенерировать свою таблицу примерно так:

<% @companies.each do |company_name, contacts| %>
    Company: <%= company_name %>
    <% contacts.each do |contact| %>
       Contact: <%= contact.name %>
          Emails : <%= contact.contact_emails.map(&:email).split(',') %>
          etc..
    <% end %>
<% end %>
0
ответ дан 7 December 2019 в 18:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: