【问题标题】:How to properly call 'render' on a partial, within a helper method?如何在辅助方法中正确调用部分“渲染”?
【发布时间】:2019-12-18 17:12:47
【问题描述】:

我正在尝试将我的一些视图逻辑移动到辅助方法中,但在渲染部分时遇到了问题。

当我使用return 语句时,它将适当地显示部分,但正如预期的那样,使用return 也会导致它跳出.each do 循环并仅呈现部分。

我没有使用return,而是尝试使用不同的语法(请参阅每个渲染实例下方的两个注释掉的行),但它们要么根本不渲染任何东西,要么生成的布局/格式已关闭(奇怪的间距和间隙)。

我设法获得我想要的结果的唯一方法是将条件登录直接嵌入到 .html.erb 本身中。但显然这是不可取的!

有什么办法可以让它正常工作吗?

帮手

  def render_appropriate_flyout_images_for(tag)
    if tag.child_tags.present?
      tag.child_tags.map(&:images).flatten.uniq.each do |image|
        return render "tasks/bottom_panel_flyout_image", image: image
        # render "tasks/bottom_panel_flyout_image", image: image
        # render partial: "tasks/bottom_panel_flyout_image", locals: { image: image }
      end
    else
      tag.images.each do |image|
        return render "tasks/bottom_panel_flyout_image", image: image
        # render "tasks/bottom_panel_flyout_image", image: image
        # render partial: "tasks/bottom_panel_flyout_image", locals: { image: image }
      end
    end
  end

来自.html.erb文件的对应方法调用

  <%= render_appropriate_flyout_images_for(tag) %>

直接嵌入到 .html.erb 文件中,这是唯一能正常显示的文件

  <% if tag.child_tags.present? %>
    <% tag.child_tags.map(&:images).flatten.uniq.each do |image| %>
      <%= render 'tasks/bottom_panel_flyout_image', image: image %>
    <% end %>
  <% else %>
    <% tag.images.each do |image| %>
      <%= render 'tasks/bottom_panel_flyout_image', image: image %>
    <% end %>
  <% end %>

更新 1:感谢@jvillian,我离解决这个问题更近了一点!

现在一切都正常显示了,除了一个小问题。出于某种原因,# 被添加到 html 输出中。每当显示多个图像时,# 将再次重复...

这是我目前用于 HELPER 的代码(注意使用 concatend.join.html_safe):

  def render_appropriate_flyout_images_for(tag)
    if tag.child_tags.present?
      tag.child_tags.map(&:images).flatten.uniq.each do |image|
        # return render "tasks/bottom_panel_flyout_image", image: image
        # render "tasks/bottom_panel_flyout_image", image: image
        # render partial: "tasks/bottom_panel_flyout_image", locals: { image: image }

        concat render partial: "tasks/bottom_panel_flyout_image", locals: { image: image }
      end.join.html_safe
    else
      tag.images.each do |image|
        # return render "tasks/bottom_panel_flyout_image", image: image
        # render "tasks/bottom_panel_flyout_image", image: image
        # render partial: "tasks/bottom_panel_flyout_image", locals: { image: image }

        concat render partial: "tasks/bottom_panel_flyout_image", locals: { image: image }
      end.join.html_safe
    end
  end

这会导致以下结果(注意图像正下方的“悬挂”#):

关于如何摆脱# 标志的任何想法?我不确定是什么导致他们在那里......

部分

<%= image_tag image.file_url(:speck),
  data: {
    crop_rotation_degrees: image.crop_rotation_degrees,
    cropw: image.crop_w,
    croph: image.crop_h,
    cropx: image.crop_x,
    cropy: image.crop_y,
    highlight_src: image.file_url(:highlight),
    imageid: image.id,
    imagepath: image_path(image),
    large_src: image.file_url(:large),
    parentimageid: image.parent_image.id,
    src: image.file_url(:small)
  }
%>

更新 2 所以说这是“已修复”,我似乎有点太草率了。今天再看一遍,部分的data: {...} 部分正在单独呈现为纯文本。

如何确保它正确包含在concat 生成的输出中?


更新 3 正如@engineersmnky 和@milgner 所指出的,生成的文本是image_tag 本身的一部分。我怀疑这是由我用来延迟加载图像的插件引起的,本质上是在查看时“覆盖”标签。不过,这是一个单独的问题 :) 至于如何在辅助方法中渲染部分内容,每个人肯定都帮助提供了答案和见解。

【问题讨论】:

  • 非常有趣的链接,@jvillian,我想你在这里有所收获。我尝试使用的部分包括&lt;%= image_tag image.file_url(:small), data: { ... } %&gt;。我会继续搞砸它,仍然不太清楚如何使用链接引用的“concat”方法......
  • 如果您对concat 感到困惑,您可以使用map 方法或该问答中也提到的each_with_object 方法。
  • 谢谢@jvillian!所以看起来我现在已经很接近了,唯一剩下的问题是有一个悬挂的# 现在显示在最后。我用这些信息更新了原始帖子。你介意看看吗?感谢您的帮助:)
  • 问题是join.html_safetag.images.each 返回图像对象的Array,因此您随后尝试加入和 html_safe 对此返回的检查。因为您使用的是 concat,所以 join.html_safe 应该是完全没有必要的

标签: ruby-on-rails


【解决方案1】:

正如linked Q&A 中所讨论的,您应该能够做到:

def render_appropriate_flyout_images_for(tag)
  if tag.child_tags.present?
    tag.child_tags.map(&:images).flatten.uniq.each do |image|
      concat render partial: "tasks/bottom_panel_flyout_image", locals: { image: image }
    end
  else
    tag.images.each do |image|
      concat render partial: "tasks/bottom_panel_flyout_image", locals: { image: image }
    end
  end
end

为了减少重复,您也可以尝试:

def render_appropriate_flyout_images_for(tag)
  images = tag.child_tags.present? ? tag.child_tags.map(&:images).flatten.uniq : tag.images
  images.each do |image|
    concat render partial: "tasks/bottom_panel_flyout_image", locals: { image: image }
  end
end

【讨论】:

  • 您的重复部分可以进一步减少为concat render partial: "tasks/bottom_panel_flyout_image", collection: images, as: :image,无需重复每个集合,因为集合会为您完成
  • 哇哦!我从来不知道,谢谢@engineersmnky 的提示!
  • 你好@jvillian(和@engineersmnky)!今天早上再看一遍,我现在注意到部分的 data: {...} 属性部分被包含为纯文本而不是 image_tag 的“部分”。我在原帖中添加了一些细节作为更新 2。有什么想法可能导致这种情况吗?
  • @Spectator6 不,它是 img 标签的一部分。正如下面@milgner 所提到的,删除= 以防止您的助手输出呈现
  • 谢谢@engineersmnky,很好!我怀疑这与我用来延迟加载图像的插件有关。这有助于我缩小查看范围。再次感谢!
【解决方案2】:

您既要从循环内部输出文本(使用concat),又要从您的帮助程序返回经过清理的 HTML 字符串。后者不是必需的。

因此,您的代码可能如下所示:

  <% render_appropriate_flyout_images_for(tag) %>

注意缺少的=:方法的输出不需要渲染。 这也意味着您可以在帮助程序中省略 .join.html_safe

【讨论】:

  • 确定 = 不是必需的吗?这让我很惊讶。但是,我经常感到惊讶。
  • 很遗憾,我手头上没有任何 Ruby。但是从我对concat 的记忆来看,它会立即将数据附加到输出缓冲区。所以我有 99.9% 的把握;)
  • 谢谢@milgner!我希望你不介意,但我正在给 jvillian 答案,因为他以前在 cmets 中帮助过我。我希望我能标记两个答案,因为你们两个都帮助我理解了发生了什么:)
  • 没问题!很高兴能够提供帮助!
  • 如果您仔细查看输出,您会注意到这里写入的不是数据属性,而是Image 对象的字符串表示形式。你的代码中一定有某个地方输出了这个对象,无意中调用了#to_s
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-27
  • 1970-01-01
相关资源
最近更新 更多