Как сделать так, чтобы один помощник работал с разными моделями? - PullRequest
1 голос
/ 01 мая 2010

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

В идеале я мог бы реорганизовать их как События, с типом как Письма, Звонки, Электронные письма, но неЯ не знаю, как расширить подклассы.

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

def show_email_status(contact, email)

  @contact_email = ContactEmail.find(:first,
     :conditions => {:contact_id => contact.id, :email_id => email.id })
  if ! @contact_email.nil?
    return @contact_email.status
  end
end

Я понял, что я, конечно, хочу знать статус того, был ли сделан вызов и контакту, поэтому я написал:

def show_call_status(contact, call)

  @contact_call = ContactCall.find(:first, 
     :conditions => {:contact_id => contact.id, :call_id => call.id })
  if ! @contact_call.nil?
    return @contact_call.status
  end
end

Я хотел бы иметь возможность просто иметьодин помощник show_status, где я могу сказать show_status (контакт, звонок) или show_status (контакт, электронная почта), и он будет знать, искать ли объект @contact_call или @ contact_email.

Да, было бы проще, если бы онбыли просто @contact_event, но я хочу сделать небольшой рефакторинг, пока я запускаю программу, и это сделало бы возможность сделать историю для данного контакта, мНамного проще.

Спасибо!

ПРИМЕЧАНИЕ. В настоящее время у меня есть статус атрибута contact_email, contact_call и т. д. Contact_email создается только при отправке электронного письма, поэтому contact_email не создается, еслиэлектронное письмо не было отправлено, и мне нужно знать, что статус «неотправлен» ...

Ответы [ 3 ]

1 голос
/ 02 мая 2010

Исходя из примера, ваши ассоциации выглядят так:

class Contact
    has_many :emails, :through => :contact_emails
    has_many :calls, :through => :contact_calls
end

и status является атрибутом ContactEmail / ContactCall, но вам нужен статус для объекта Email / Call, затем (на основе ответа Кандада здесь):

class Contact 
  def event_status(event)
    event_type = event.class.name
    foreign_key = ("%s_id" % event_type.downcase).to_sym

    assoc = "Contact#{event_type}".tableize
    contact_event = send(:assoc).first(:conditions => {foreign_key => event.id})
    contact_event.try(:status) 
  end
end
0 голосов
/ 02 мая 2010

Вы можете переместить помощника на модель Contact.

class Contact < ActiveRecord::Base

  has_many :contact_emails
  has_many :contact_calls
  has_many :contact_letters

  def event_status event
    assoc_name = "Contact#{event.class.name}".pluralize.underscore
    foreign_key = "%s_id" % event.class.name.underscore
    ce = send(assoc_name).first(:conditions => {foreign_key => event.id})
    ce ? ce.status : nil
  end

end

Теперь вы можете получить статус следующим образом:

contact.event_status(email1)
contact.event_status(letter2)
contact.event_status(call12)

Это облегчает потребность в разных помощниках. Один метод для решения различных событий.

0 голосов
/ 01 мая 2010

Поскольку у вас уже есть show_call_status и show_email_status, вы можете написать третий show_letter_status.

Тогда используйте это:

def show_status(contact, call_or_email_or_letter)
  model_name = call_or_email_or_letter.class.name.tableize.singularize
  send "show_#{model_name}_status", contact, call_or_email_or_letter
end
...