如何在rails中重构需要这么多的for循环?

时间:2010-05-15 04:10:20

标签: ruby-on-rails for-loop

我需要帮助重构这个多循环的东西。这就是我所拥有的:

广告系列has_many联系人
Campaign还有许多模板,它们是模板:(电子邮件,电话和信件)。

因为我正在寻找每个的逾期,我创建了一个名为Event的数组,我想循环包含['email','call','letter']。

我需要列出属于广告系列的每个联系人“过期”的所有电子邮件,电话和信件。逾期由from_today方法决定,该方法查看联系人在系统中输入的日期以及任何给定事件需要传递的天数。 from_today()输出从今天开始为给定联系人完成事件的天数。

以下是我所做的,它适用于所有联系人的广告系列中的所有电子邮件。我打算尝试创建另一个do循环来更改类名。

不确定从哪里开始:named_scope,将某些内容推送到方法,等等,或者 - 最少能够动态更改类名,以便至少在不同事件中循环三次而不是重复代码三次:

<% @campaigns.each do |campaign| %>
   <h2><%= link_to campaign.name, campaign %></h2>

   <% @events.each do |event| %>
       <%= event %>
       <% for email in campaign.emails %>
          <h4><%= link_to email.title, email  %> <%= email.days %> days</h4>

          <% for contact in campaign.contacts.find(:all, :order => "date_entered ASC" ) %>
             <% if (from_today(contact, email.days) < 0) %>
                <% if show_status(contact, email) == 'no status'%>
                    <p> <%= full_name(contact) %> 
                        is <%= from_today(contact,email.days).abs%> days overdue:
                        <%= do_event(contact, email) %>
                    </p>
                <% end %>
             <% end %>
          <% end %>
       <% end %>
     <% end %>
<% end %>

2 个答案:

答案 0 :(得分:1)

我将每个资源的输出放入部分,如下所示:

<% @campaigns.each do |campaign| %>
  <h2><%= link_to campaign.name, campaign %></h2>
  <%= render 'events', :events => campaign.events %>
<% end %>

然后在app / views / campaigns / _events.html.erb

<% events.each do |event| %>
  <%= event %>
  <%= render 'emails', :emails => event.emails %>
<% end %>

然后在app / views / campaigns / _emails.html.erb

<% emails.each do |email| %>
  <h4><%= link_to email.title, email  %> <%= email.days %> days</h4>
  <%= render 'contacts', :contacts => email.contacts.all(:order => "date_entered ASC", :email => email) %>
<% end %>

然后在app / views / campaigns / _contacts.html.erb

<% contacts.each do |contact| %>
  <% if (from_today(contact, email.days) < 0) %>
    <% if show_status(contact, email) == 'no status'%>
      <p> <%= full_name(contact) %> 
          is <%= from_today(contact,email.days).abs%> days overdue:
          <%= do_event(contact, email) %>
      </p>
    <% end %>
  <% end %>
<% end %>

答案 1 :(得分:1)

为了补充Patrick的答案,我还会使用render的:collection选项来进一步简化这一点,例如:有一个部分_contact.html.erb来呈现每个联系人:

<% if (from_today(contact, email.days) < 0) %>
    <% if show_status(contact, email) == 'no status'%>
      <p> <%= full_name(contact) %> 
          is <%= from_today(contact,email.days).abs%> days overdue:
          <%= do_event(contact, email) %>
      </p>
    <% end %>
  <% end %>
<% end %>

然后使用

呈现contacts集合
= render :partial => "contact", :collection => @contacts

我也不会在视图中进行查找,而是在控制器中设置所有变量,并可能将所有条件代码移动到帮助器中。最好从视图中保留尽可能多的逻辑。