Есть ли у вас has_many
настройки ассоциаций в Contact
со ссылкой на другие модели? Что-то вроде:
class Contact < ActiveRecord::Base
has_many :contact_emails
has_many :contact_calls
has_many :contact_letters
end
Если это так, вы можете создать метод last_event
для модели Contact
:
def latest_event
[contact_emails, contact_calls, contact_letters].map do |assoc|
assoc.first(:order => 'date_sent DESC')
end.compact.sort_by { |e| e.date_sent }.last
end
Обработка nil
При использовании метода latest_event
вы получите nil
, если нет связанных записей. Есть несколько способов обойти это. Во-первых, сначала нужно проверить на ноль что-то вроде:
contact.latest_event && contact.latest_event.date_sent
В поздних версиях Rails / Ruby вы также можете использовать Object#try
, который будет вызывать метод, если он существует:
contact.latest_event.try(:date_sent)
Я предпочитаю не использовать это, поскольку он не проверяет nil
, но только если объект может ответить на метод. Это может привести к некоторым интересным ошибкам, если вы ожидаете nil
, если объект nil
, но вызывает метод, на который nil
сам отвечает.
Наконец, мой предпочтительный метод для простого случая - использовать камень andand
, который обеспечивает Object#andand
. Это значительно сокращает указанный выше безопасный случай и несколько раз сохраняет вызовы latest_event
:
contact.latest_event.andand.date_sent
date_sent
, nil
и Вы.
Для вашего примера использования звонка to_s(:long)
, вы можете использовать &&
или andand
:
contact.latest_event.andand.date_sent.andand.to_s(:long)
* * Или тысяча сорок-девять
contact.latest_event && contact.latest_event.date_sent.to_s(:long)
Первое безопаснее, если date_sent
само по себе может быть nil
. Без использования andand
это можно записать как:
contact.latest_event &&
contact.latest_event.date_sent &&
contact.latest_event.date_sent.to_s(:long)
что довольно сложно и громоздко на мой взгляд. Я бы порекомендовал посмотреть andand