【问题标题】:How to loop in a helper method and render a partial for each looped instance. Rails如何循环进入辅助方法并为每个循环实例渲染一个部分。导轨
【发布时间】:2018-09-15 21:57:57
【问题描述】:

我的 Rails 应用中有以下视图:

app/views/matches/_round.html.erb

matches.each do |match|
  # some html code here
  <%= predictions(@pool, match, @current_participant) %>
  # more html code here
end

以及以下辅助方法:

app/helpers/match_predictions_helper.rb

  def predictions(pool, match, participant)
    if match.can_be_predicted_in?(pool)
      random_predictions_for_match = match.random_predictions_in_pool(pool)
      if random_predictions_for_match.empty?
        "<h3> No predictions available yet </h3>".html_safe
      else
        random_predictions_for_match.each do |prediction|
          tooltip_title = "undisclosed participant"
          outcome_class = ""
          render partial: 'match_predictions/prediction', locals: { match: match, prediction: prediction, tooltip_title: tooltip_title, outcome_class: outcome_class }
        end
      end
    else
      match.predictions_in_pool(pool, current_user).each do |prediction|
        tooltip_title = prediction.participant.username
        outcome_class = prediction.class_name
        render partial: 'match_predictions/prediction', locals: { match: match, prediction: prediction, tooltip_title: tooltip_title, outcome_class: outcome_class }
      end
    end
  end

所以我的意图是显示每场比赛的预测列表,但该列表会根据某些条件而变化。我可以通过在视图中包含以下逻辑来实现这一点:

app/views/matches/_round.html.erb

matches.each do |match|
<% if match.can_be_predicted_in?(@pool) %>
  <% random_predictions_for_match = match.random_predictions_in_pool(@pool) %>
  <% if random_predictions_for_match.empty? %>
    <h3> No predictions to spy available yet </h3>
  <% else %>
    <% random_predictions_for_match.each do |prediction| %>
      <% tooltip_title = "undisclosed participant" %>
      <% outcome_class = "" %>
      <%= render partial: 'match_predictions/prediction', locals: { match: match, prediction: prediction, tooltip_title: tooltip_title, outcome_class: outcome_class } %>
    <% end %>
  <% end %>
<% else %>
  #etc, etc, the rest of the code below.
end

不过,我想将逻辑从视图中剥离出来。到目前为止,我遇到的是,当将each 循环放在帮助程序中时,在我看来,我返回了一个数组,其中包含所有循环的对象,而不是每个循环项的预期部分呈现。助手正在输出循环本身而不是其中的内容(即要渲染的部分)。奇怪的是,在我的服务器日志中,我看到每次迭代都会呈现部分内容。

我经常使用助手和部分渲染循环迭代产生的对象,但我注意到我不太了解render 和助手在尝试将循环卡在助手中时的工作方式。

任何帮助将不胜感激。

更接近解决方案,基于下面的 Taryn 建议

因此,predictions 帮助器的输出将是一个数组,因此您必须在视图中循环遍历它,所以我这样做了。

matches.each do |match|
<% predictions(@pool, match, @current_participant).each do |prediction| %>
  <%= prediction %>
<% end %>
end

另外,出于同样的原因,作为字符串的第一个条件输出也应该放入results 数组中:

# more code here
if random_predictions_for_match.empty?
  results << ["<h3> No predictions to spy available yet </h3>".html_safe]
else
# more code here

我仍然遇到问题,因为浏览器不会将部分呈现的内容读取为 html,所以现在我已将所有部分内容移动到另一个帮助程序,现在在调用部分内容的地方调用该帮助程序。这有效并减少了视图中的逻辑,除了额外的predictions 每个循环。

任何更多关于清洁代码的建议表示赞赏。

【问题讨论】:

    标签: ruby-on-rails partials


    【解决方案1】:

    首先,总切线:您知道不必为每个 LOC 打开/关闭&lt;% 标签吗?它们跨多行工作......这将减少模板中的一些噪音,例如:

    <% matches.each do |match|
     if match.can_be_predicted_in?(@pool)
       random_predictions_for_match = match.random_predictions_in_pool(@pool) 
       if random_predictions_for_match.empty? %>
        <h3> No predictions to spy available yet </h3>
      <% else 
         random_predictions_for_match.each do |prediction| 
           tooltip_title = "undisclosed participant" 
           outcome_class = "" %>
          <%= render partial: 'match_predictions/prediction', locals: { match: match, prediction: prediction, tooltip_title: tooltip_title, outcome_class: outcome_class } %>
        <% end 
       end 
     else %>
      # etc, etc, the rest of the code below.
    <% end %>
    

    其次,方法的返回值(即使对于帮助程序)是方法中的最后一条语句......在这种情况下是循环本身,而不是在循环中调用的渲染。这就是为什么 rails 认为您打算显示循环的返回值...

    您可能必须存储渲染结果,然后在最后返回它们,我猜(这不是经过错误测试)类似于:

      def predictions(pool, match, participant)
        results = []
        if match.can_be_predicted_in?(pool)
          random_predictions_for_match = match.random_predictions_in_pool(pool)
          if random_predictions_for_match.empty?
            return "<h3> No predictions available yet </h3>".html_safe
          else
            random_predictions_for_match.each do |prediction|
              tooltip_title = "undisclosed participant"
              outcome_class = ""
              results << render(partial: 'match_predictions/prediction', locals: { match: match, prediction: prediction, tooltip_title: tooltip_title, outcome_class: outcome_class })
            end
          end
        else
          match.predictions_in_pool(pool, current_user).each do |prediction|
            tooltip_title = prediction.participant.username
            outcome_class = prediction.class_name
            results << render(partial: 'match_predictions/prediction', locals: { match: match, prediction: prediction, tooltip_title: tooltip_title, outcome_class: outcome_class })
          end
        end
        results
      end
    

    【讨论】:

    • Taryn 非常感谢您的建议。这绝对是有道理的。出于某种原因,我无法选择在数组中收集渲染的部分。但是,我已经尝试了您建议的解决方案,但是当 if 语句或块未正确关闭时,我得到了一种语法错误。我已经检查过了,问题肯定是渲染部分被推入数组results &lt;&lt;...etc. 的行。我尝试添加括号并将它们更改为其他地方但没有成功。任何想法为什么语法错误。
    • hmmm...也许它希望它是一个字符串...例如results = ""和results += ...我会从渲染一些简单的东西开始测试它(例如一个带有预测的字符串id 而不是部分模板)并检查所有其余的逻辑是否正常工作......然后添加没有本地人的渲染......看看它在什么时候中断。
    • 谢谢塔林。我现在再试一次。它一定很简单。这让我感到困惑,因为它在某些时候起作用了,我看不到它是什么,并且失去了上帝知道的改变。我会按照你的调试建议,看看我是否幸运
    • 我遇到了错误。我认为Ruby中的空格无关紧要。在这种情况下不是!我在render 和第一个括号之间添加了一个空格。助手现在返回一个包含每个渲染部分的数组。但是,浏览器不会将其作为 HTML 读取。我尝试在部分帮助程序的末尾使用html_safe,希望能够轻松修复,但没有成功。我可以通过调用另一个助手而不是渲染部分来解决整个问题,所以最后我将能够离开没有逻辑的视图。但是,如果您能提出最后一个 Rails 魔术技巧来解决这个问题,我们将不胜感激
    • 重新思考问题实际上是问题在于,使用您提出的方法,无论我是在数组中收集部分还是其他辅助输出,匹配 each 循环内的辅助输出将永远是一个数组。这意味着我必须在我的主视图中循环遍历它,并且当辅助方法不输出数组时(因为这是第一个条件的情况,如果没有放入另一个数组,它会破坏代码。我会尝试这个并报告它是否有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 2016-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-22
    相关资源
    最近更新 更多