我为每个联系人提供一个广告系列,其中包含三种类型的模型:电子邮件,通话和信函。
当为特定联系人执行电子邮件(呼叫或信件)时,我有一个Contact_Email(_or_Call_or_Letter),它同时属于联系人和模型(Email_or_Call_or_Letter)。
每个Contact_Email例如配对都有:date_sent属性。每个Contact_Call和Contact_Letter都是如此。
如何找到最新的所有内容?
以下是我编写的代码,可以找到最新的电子邮件和我的调查结果重新输入Call和Letter的类似代码,但后来又坚持如何对所有这些代码执行.max:
def last_email(contact)
#get campaign the contact belongs to
@campaign = Campaign.find_by_id(contact.campaign_id)
@last_email = ContactEmail.find(:last,
:conditions => "contact_id = #{contact.id}",
:order => "date_sent DESC")
@last_call = ContactCall.find(:last,
:conditions => "contact_id = #{contact.id}",
:order => "date_sent DESC")
@last_letter = ContactLetter.find(:last,
:conditions => "contact_id = #{contact.id}",
:order => "date_sent DESC")
# how do I get the latest of all of these to display?
@email_template = Email.find_by_id(@last_email.email_id)
if @last_email.nil?
return "no email sent"
else
return @last_email.date_sent.to_s(:long) + link_to('email was sent', @email_template)
end
end
问题1:凭借我所拥有的,我如何有效地找到@last_event,因为我可以找到每个联系人的最后一封电子邮件,最后一个电话和最后一封信?
问题2:如何删除我必须为每个模型编写的重复代码?
答案 0 :(得分:1)
您是否在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
。有几种方法可以解决这个问题。第一个是先检查nil,例如:
contact.latest_event && contact.latest_event.date_sent
在Rails / Ruby的后期版本中,你也可以使用Object#try
,如果它存在,它将调用该方法:
contact.latest_event.try(:date_sent)
我不想使用它,因为它不检查nil
,但仅当对象可以响应方法时。如果您希望nil
,如果对象是nil
但是正在调用nil
本身响应的方法,则会导致一些有趣的错误。
最后,我对简单案例的首选方法是使用提供Object#andand
的{{3}} gem。这大大缩短了上述安全案例,并多次保存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
答案 1 :(得分:0)
问题1:
只做
@last_event = [@last_letter, @last_email, @last_call].sort_by{|m| m.date_sent}.first
问题2:
这更有趣。这种情况取决于模型的确切外观,但您可能需要考虑此类方案的单表继承。