everyone: I am also open to just straight-up refactoring what I’m finding to be pretty repetitive, but to give a baseline of how it’s working….
I have for every contact a Campaign, which has_many of three types of Models: Email, Call, and Letter.
When an Email (Call or Letter) has been executed for a specific contact, I have a Contact_Email(_or_Call_or_Letter) which belongs to both the Contact and the Model (Email_or_Call_or_Letter).
Each Contact_Email for example pairing has a :date_sent attribute. So does each Contact_Call and Contact_Letter.
How do I find the latest of all of them?
Here is the code I wrote that can find the latest Email and my finding retyping similar code for Call and Letter, but then stuck on how to do a .max on all of them:
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
Question 1: With what I have, how can I find effectively @last_event given I can find the last Email, last Call, and last Letter for every contact?
Question 2: How can I remove the repetitive code that I have to write for each Model?
Do you have
has_manyassociations setup inContactreferring to the other models? Something like:If so, you can then create a
last_eventmethod on theContactmodel:Handling
nilWhen using the
latest_eventmethod you will getnilif there are no associated records. There are a couple of ways you can workaround this. The first is to check for nil first with something like:On late versions of Rails/Ruby you can also use
Object#trywhich will call the method if it exists:I prefer not to use this as it doesn’t check for
nilbut only if the object can respond to a method. This has cause some interesting errors if you expectnilif the object isnilbut are calling a method whichnilitself responds to.Finally, my preferred method for the simple case is to use the
andandgem which providesObject#andand. This greatly shortens the safe case above and saves calling oflatest_eventmultiple times:date_sent,niland You.For your example usage of calling
to_s(:long), you could either use&&orandand:or
The first is safer if
date_sentitself may benil. Without usingandandthis could be written as:which is rather complex and unwieldily in my opinion. I would recommend looking into
andand