【问题标题】:Are recursion functions not supported in .erb templates?.erb 模板不支持递归函数吗?
【发布时间】:2018-08-01 22:01:06
【问题描述】:

好的,基本上我有这样的东西:

someView.erb

 <ul>
    <% @objects.each do |object| %>
      <%= printAllChildObjects(object) %>
    <% end %>
 </ul>

app.rb

def printAllChildObjects(object)
   "<li>#{object.attributes['name']}</li>"
    if object.children.first.name == "Error"
      break
    else 
      object.elements.first.each do |innerObject| 
         printAllChildObjects(innerObject)
      end
    end
end

TL:DR;我正在使用 REXML 解析一些 XML 文件(Ruby 内置的 XML 解析器,由于一些可笑的公司原因,我不能使用 Nokogiri)。该 XML 文件的节点中可能嵌套了也可能没有嵌套的子节点,并且其中的子节点数量不等。我通过使用puts 语句并观察终端尝试了我的递归函数,它按预期工作。

但是,当我尝试合并上面的视图文件时,我得到了带有三个点的空框,即[ ... ],每个对象都应该在其中打印。疯狂的是,框的数量与对象的数量相匹配,在使用 Chrome 开发工具检查 html 时,您可以看到整个对象节点,而不仅仅是 object.attributes['name'](即节点中的名称属性)。

另外,当我删除递归调用并在函数中保留"&lt;li&gt;#{object.attributes['name']}&lt;/li&gt;" 部分时,HTML 再次工作!所以我相当肯定递归是破坏 HTML 渲染的原因。有什么办法可以解决这个问题吗?即使是最细微的见解,我也会感激不尽。

哦,我使用的是 Sinatra,而不是 Rails。

【问题讨论】:

  • 如果没有显式返回任何内容,Ruby 将返回最后计算的表达式。如果明确不想连接到视图的输出缓冲区,则应继续附加到对象并返回它。
  • 我认为得到的是因为object.elements.first.each 正在返回三个对象,这就是.each 的工作方式。尝试将.each 更改为.collect。不过,这可能不是你所需要的。
  • @JoshBrody 你听说过concat 的替代方法吗?因为那是Rails 方法?

标签: ruby-on-rails ruby sinatra erb


【解决方案1】:

尝试类似:

<ul>
  <% @objects.each do |object| %>
    <% print_children_for(object).flatten.each |li_tag| %>
     <%= li_tag %>
    <% end %>
  <% end %>
</ul>

def print_children_for(object, parent = nil)
  mark_up = []
  mark_up << parent.nil? ? "<li>#{object.attributes['name']}</li>" : parent

  return mark_up if object.children.first.name == "Error"
  object.elements.first.each do |innerObject| 
     print_children_for(innerObject, markup)
  end
end

需要进行一些调整(在某些地方保护 nil 值),我正在即时执行此操作,没有检查它,但也许类似的东西可以帮助您。

【讨论】:

    【解决方案2】:

    按照附加到某个 HTML 缓冲区并显式返回函数的建议,以下代码解决了我的问题:

    def printAllChildObjects(refObject, html)
      html << "<li>#{refObject.attributes['name']}</li>"
    
      if refObject.children.first.name == "Error"
         break
      else
         refObject.elements.first.each do |innerObject|
             return printAllChildObjects(innerObject, html)
         end
      end
    
     return html
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-08
      • 1970-01-01
      • 2021-12-25
      • 1970-01-01
      • 1970-01-01
      • 2022-11-03
      • 1970-01-01
      • 2014-01-29
      相关资源
      最近更新 更多