包含 'if' 语句的嵌套循环

Nested loop with 'if' statements

我正在尝试遍历选项数组,并检查每个选项以查看它是否与不同数组中的不同选项匹配。如果两个选项匹配,做一件事,如果不匹配,做另一件事。

我有3^2个可用选项,它运行了九次。它变为 (true, false, false)(false, true, false)(false, false, true),这并不理想。相反,我希望看到类似以下内容的内容:(true)(false)(true).

它位于我前端的一个 erb 文件中。我意识到那里不应该有逻辑,很高兴提出重构建议,但确实计划在我弄清楚如何使循环工作后将其移出。

前端代码:

<% @available_sites.each do |available_site| %>
  <% @sites.each do |site| %>
    <% if site.review_site == available_site.name %>
      <div class="site-row columns">
        <div class="column col-4 col-md-10 col-mx-auto">
          <div class="site-tile">
            <a href="<%= site.direct_review_url %>" style="background-image: url(<%= image_path("review_site_logos/#{site.review_site}.png")%>); background-size: cover;"></a>
          </div>
        </div>
        <div class="column col-4 col-md-10 col-mx-auto">
          <span>Average Rating: <%= site.average_rating %></span>
          <span>Review Site: <a href="<%= site.direct_review_url %>"><%= site.review_site %></a></span>

        </div>
        <div class="column col-4 col-md-10 col-mx-auto is-flex-centered request-row-buttons">
          <%= link_to 'Show', [site.location, site] %>
          <%= link_to 'Edit', [:edit, site.location, site] %>
          <%= link_to 'Destroy', [site.location, site], method: :delete, data: { confirm: 'Are you sure?' } %>
        </div>
      </div>
    <% elsif site.review_site != available_site.name %>
      <div class="site-row columns">
        <div class="column col-4 col-md-10 col-mx-auto">
          <div class="site-tile">
            <a href="<%= available_site.link_to_info %>" style="background-image: url(<%= image_path("review_site_logos/#{available_site.name}.png")%>); background-size: cover;"></a>
          </div>
        </div>
        <div class="column col-4 col-md-10 col-mx-auto">
          <span>Sign Up for <%= available_site.name %> Business Page: <%= available_site.link_to_signup %></span>
          <span>Review Site: <a href="<%= site.direct_review_url %>"><%= site.review_site %></a></span>

        </div>
        <div class="column col-4 col-md-10 col-mx-auto is-flex-centered">
          <%= link_to "Add #{available_site.name} to Review App", new_location_site_path(review_site: "#{available_site.name}"), class: 'btn btn-primary' %>
        </div>
      </div>
    <% end %>
  <% end %>
<% end %>

相关控制器代码sites_controller.rb-policy_scope授权:

def index
    @sites = policy_scope(@location.sites)
    @available_sites = AvailableSite.all
  end

相关架构代码

create_table "sites", force: :cascade do |t|
    t.bigint "location_id"
    t.string "review_site"
    t.string "direct_review_url"
    t.string "place_id"
    t.decimal "average_rating"
    t.jsonb "extra_data", default: {}, null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.integer "rating_count"
    t.index ["extra_data"], name: "index_sites_on_extra_data", using: :gin
    t.index ["location_id"], name: "index_sites_on_location_id"
  end
create_table "available_sites", force: :cascade do |t|
    t.string "name"
    t.string "link_to_info"
    t.string "link_to_signup"
    t.string "base_review_url"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["name"], name: "index_available_sites_on_name"
  end

我正在寻找 help/a 处理嵌套循环的新方向。

为了确保我们达成共识,我将重申您的问题:

您有一个 AvailableSite 的列表,并且您希望显示不同的信息,具体取决于您是否有可见的 Site

如果那是准确的,您将要使用 find。类似于:

<% @available_sites.each do |available_site| %>
  <% site = @sites.find { |s| s.review_site == available_site.name } %>

  <% if site.present? %>
    <%# view fragment when you have a site %>
  <% else %>
    <%# view fragment when you don't have a site %>
  <% end %>
<% end %>

这将只输出每个 AvailableSite 的一组元素。

首先,让我们通过将两个视图部分移动到实际的部分文件中来使其更易于解析和维护。这样我们就有了简单的

<% @available_sites.each do |available_site| %>
  <% @sites.each do |site| %>
    <% if site.review_site == available_site.name %>
       <% render partial: "sites/site_available", locals: {site: site}>
    <% else %>
       <% render partial: "sites/site_unavailable", locals: {site: site}>
    <% end %>
  <% end %>
<% end %>

更好玩!

接下来,我们不需要在嵌套循环内渲染;这就是为什么您得到 9 个而不是 3 个效果图。 @sites 需要一个外循环。在每个循环中,它将 (1) 检查可用性,(2) 渲染。这看起来更像

<% @sites.each do |site| %>
  <% if site_available?(@site, @available_sites) %>
     <% render partial: "sites/site_available", locals: {site: site}>
  <% else %>
     <% render partial: "sites/site_unavailable", locals: {site: site}>
  <% end %>
<% end %>

你有很多选择可以实际做什么,或者代替 site_available?,包括:

  1. 定义为辅助方法,查看代码如上。不是我推荐的方法,但它会完成工作。
  2. 使用@available_sites.map(&:name).include?(@site.name)。现在更明显的是这是一个循环(include? 会循环),但是渲染发生在这个循环之外。有点低效,但 AvailableSite.all 也是如此,所以现在可能没问题:-)
  3. 使用演示者:这只是一个简单的 Ruby class,它会将 site 作为 initialize 方法的参数,并具有额外的逻辑和您可以在不污染模型、视图或控制器的情况下添加的属性(例如 @available)。如果这变得更复杂,我总是主张从这里开始,但现在可能有点笨手笨脚。

class AvailableSitePresenter
  def new(site, available_sites)
    @site = site
    @available = available_sites.map(&:name).include?(@site.name)
  end

  def available?
    @available
  end
end