ruby-on-rails - 如何在 Rails 中调用类似模型时使此代码(帮助程序)干燥?

标签 ruby-on-rails models dry helper

最终目标是创建一个名为 show_status(contact,event) 的助手。

事件可以是任何对象,电子邮件、信件等。发送给联系人的电子邮件模板的组合是一个特定的记录ContactEmail。因为每个事件都有不同的对应模型,所以我需要进行 .find 操作,所以我有重复。一定会有更好的办法!

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.to_s + " (" + @contact_email.date_sent.to_s + ")"
    else 
      return "no 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 "sent " + @contact_call.date_sent.to_s(:long)
    else
      return "no status"
    end
  end

  def show_letter_status(contact, letter)

    @contact_letter = ContactLetter.find(:first, :conditions => {:contact_id => contact.id, 
                                                              :letter_id => letter.id })
    if ! @contact_letter.nil?
      return "sent " + @contact_letter.date_sent.to_s(:long)
    else
      return "no status"
    end
  end

  def show_voicemail_status(contact, voicemail)

    @contact_event = ContactEvent.find(:first, :conditions => {:contact_id => contact.id, 
                                                              :event_id => voicemail.id,
                                                              :type => "voicemail"})
    if ! @contact_event.nil?
      return "sent " + @contact_event.date_sent.to_s(:long)
    else
      return "no status"
    end
  end

  def show_postalcard_status(contact, postalcard)

    @contact_postalcard = ContactPostalcard.find(:first, :conditions => {:contact_id => contact.id, 
                                                              :postalcard_id => postalcard.id })
    if ! @contact_postalcard.nil?
      return "sent " + @contact_postalcard.date_sent.to_s(:long)
    else
      return "no status"
    end
  end

  def show_status(contact, call_or_email_or_letter_or_voicemail)

    model_name = call_or_email_or_letter_or_voicemail.class.name.tableize.singularize
    send "show_#{model_name}_status", contact, call_or_email_or_letter_or_voicemail
  end

最佳答案

试试这个:

def show_status(contact, target)
  target_class= target.class.name
  target_id   = target_class.foreign_key.to_sym
  klass       = "Contact#{target_class}".constantize

  r = klass.first(:conditions => {:contact_id => contact.id, 
              target_id => target.id})

  return "no status" unless r

  # If you want to treat ContactEmail differently then use the next line
  #return "#{r.status} (#{r.date_sent})" if target.is_a?(ContactEmail)

  "sent (#{r.date_sent.to_s(:long)})" 
end

用法:

contact = Contact.find(..)
email   = Email.find(..)
letter  = Letter.find(..)
call    = Call.find(..)

show_status(contact, email)
show_status(contact, letter)
show_status(contact, call)

编辑 1

更好的方法是向 Contact 模型添加一个方法。

class Contact < ActiveRecord::Base
  # assuming you have following associations
  has_many :contact_emails
  has_many :contact_calls
  has_many :contact_letters
  # etc..


  def communication_status target
    target_class= target.class.name
    target_id   = target_class.foreign_key.to_sym
    assoc_name  = "contact_#{target_class.tableize}"
    r = send(assoc_name).send("find_by_#{target_id}", target.id) 
    return "no status" unless r
    "sent (#{r.date_sent.to_s(:long)})" 
  end

end

用法:

contact = Contact.find(..)
email   = Email.find(..)
letter  = Letter.find(..)
call    = Call.find(..)

contact.communication_status(email)
contact.communication_status(email)
contact.communication_status(letter)
contact.communication_status(call)

关于ruby-on-rails - 如何在 Rails 中调用类似模型时使此代码(帮助程序)干燥?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3527988/

相关文章:

javascript - 将多个 bool 检查简化为一个检查

ruby-on-rails - rails 事件记录遍历行

javascript - jQuery Remotipart 发送 [object Object] 到服务器

ruby-on-rails - 如何在Rails应用程序中遍历所有模型?

python - Django 模型 : Use multiple values as a key?

ruby - 使用 nokogiri 干搜索网站的每一页

ruby-on-rails - 神秘的ruby语法错误

ruby-on-rails - 在 web 和 worker dynos 之间拆分 postgres 连接?

ruby-on-rails - 如何将Rails模型记录与代码关联?

c# - MVP、泛型和 DRY