Вложенный цикл с операторами if - PullRequest
0 голосов
/ 04 октября 2018

Я пытаюсь перебрать массив опций и проверить каждую опцию, чтобы увидеть, соответствует ли она другой опции в другом массиве.Если два варианта совпадают, сделайте одно, если они не совпадают, сделайте другое.

У меня есть 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

Я ищу помощь / новое направление по обработке вложенных циклов.

Ответы [ 2 ]

0 голосов
/ 04 октября 2018

Во-первых, давайте упростим анализ и поддержку, переместив две части представления в реальные частичные файлы.Таким образом, у нас есть просто

<% @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, который примет 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
0 голосов
/ 04 октября 2018

Просто чтобы убедиться, что мы находимся на одной странице, я повторю вашу проблему:

У вас есть список 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.

...