【问题标题】:Railtie(gem): How do i include and render erb partials?Railtie(gem):我如何包含和渲染 erb 部分?
【发布时间】:2014-05-20 10:15:44
【问题描述】:

我正在开发 Railtie(gem),用于嵌入 YouTube、Vimeo 等视频。

在这个 gem 中我想要一个视图助手,这样我就可以调用 embed_video(embeddable, width, height)

所以我创建了助手作为助手,它可以工作,但我想重构它以使用部分来使其更清洁,但我发现很难做到这一点。

帮手:

module ViewHelpers
  def embed_video(embeddable, width, height)
    if embeddable.video_on_youtube?
      content_tag :iframe, nil, width: width, height: height,
        src: "//www.youtube.com/embed/#{embeddable.video_id}",
        allowfullscreen: true, frameborder: 0
    elsif embeddable.video_on_vimeo?
      content_tag :iframe, nil, width: width, height: height,
        src: "//player.vimeo.com/video/#{embeddable.video_id}",
        webkitallowfullscreen: true, mozallowfullscreen: true,
        allowfullscreen: true, frameborder: 0
    elsif embeddable.video_on_dailymotion?
      content_tag :iframe, nil, width: width, height: height,
        src: "//www.dailymotion.com/embed/video/#{embeddable.video_id}",
        webkitallowfullscreen: true, mozallowfullscreen: true,
        allowfullscreen: true, frameborder: 0
    elsif embeddable.video_on_veoh?
      %Q{
        <object width='#{width}' height='#{height}' id='veohFlashPlayer' name='veohFlashPlayer'>
          <param name='movie' value='http://www.veoh.com/swf/webplayer/WebPlayer.swf?version=AFrontend.5.7.0.1446&permalinkId=#{embeddable.video_id}&player=videodetailsembedded&videoAutoPlay=0&id=anonymous'></param>
          <param name='allowFullScreen' value='true'></param>
          <param name='allowscriptaccess' value='always'></param>
          <embed src='http://www.veoh.com/swf/webplayer/WebPlayer.swf?version=AFrontend.5.7.0.1446&permalinkId=#{embeddable.video_id}&player=videodetailsembedded&videoAutoPlay=0&id=anonymous' type='application/x-shockwave-flash' allowscriptaccess='always' allowfullscreen='true' width='#{width}' height='#{height}' id='veohFlashPlayerEmbed' name='veohFlashPlayerEmbed'>        </embed>
        </object>
      }.html_safe
    #
    # And more providers...
    #
  end
end

使用部分我想这样写:

module ViewHelpers
  def embed_video(embeddable, width, height)
    if embeddable.video_on_youtube?
      render 'youtube', embeddable: embeddable, width: width, height: height
    elsif embeddable.video_on_veoh?
      render 'veoh'#...etc
    end
  end
end

我尝试的解决方案:

  • 创建文件夹: lib/embeddable/partials

  • 为 veoh 添加部分: lib/embeddable/partials/_veoh.html.erb

在 railtie.rb 中添加视图路径

module Embeddable
  class Railtie < Rails::Railtie
    # ...load view helpers... #

    initializer 'embeddable.add_autoload_paths', :before => :set_autoload_paths do |app|
      app.config.autoload_paths << app.root.join("lib/embeddable/partials").to_s
    end

    # My attempt at adding the partials to the view path
    initializer 'embeddable.add_view_paths', :after => :add_view_paths do |app|
      ActiveSupport.on_load(:action_controller) do
        append_view_path app.root.join("lib/embeddable/").to_s
      end
    end
  end
end

当我尝试渲染视图时,出现以下错误:

ActionView::MissingTemplate: Missing partial partials/veoh with {:locale=>[:nb], :formats=>[:html], :handlers=>[:erb, :builder, :raw, :ruby, :coffee, :rabl, :haml]}. Searched in:
  * "/home/me/Arbeid/the_application/app/views"
  * "/home/me/.rvm/gems/ruby-2.1.0/gems/kaminari-0.15.1/app/views"
  * "/home/me/Arbeid/the_application/lib/embeddable"

【问题讨论】:

  • Partials 不应该在助手中使用。如果你想调用其他部分,你最好使用部分而不是助手。
  • 不过在这种情况下对我来说是完美的。为什么我不应该在助手中使用部分?以及如何在 railtie 中包含部分内容?
  • 这不是它们的用途。 Helpers 用于返回少量的 html。
  • 也就是说,你应该仍然可以使用render :partial =&gt; "path/to/youtube", :locals =&gt; {:embeddable =&gt; embeddable, :width =&gt; width, :height =&gt; height}
  • 我也是这么想的,但它只在使用 gem 的应用程序的 app/view 文件夹中查找部分内容。我尝试将 lib/embeddable 添加到 view_paths(参见上面的示例),但不幸的是我没有设法让它工作。

标签: ruby-on-rails ruby-on-rails-4 railtie


【解决方案1】:

经过大量的跟踪和错误后,我设法让它工作。这是我必须做的:

我改变了这个:

initializer 'embeddable.add_view_paths', :after => :add_view_paths do |app|
  ActiveSupport.on_load(:action_controller) do
    append_view_path app.root.join("lib/embeddable/").to_s
  end
end

进入这个:

initializer 'embeddable.add_view_paths', :after => :add_view_paths do |app|
  ActiveSupport.on_load(:action_controller) do
    append_view_path "#{Gem.loaded_specs['embeddable'].full_gem_path}/lib/embeddable"# <- this is the change
  end
end

现在我可以像这样从助手渲染部分:

render 'partials/youtube', id: video_id, width: width, height: height

【讨论】:

  • 我又想了一遍:你为什么不把视图放在应用程序/引擎中的视图中?
  • 我没有创建引擎的原因仅仅是因为 gem 真的很小。它只包含一个问题,以及我在这个问题中发布的代码。我认为让它成为一个带有模型、控制器等的引擎有点矫枉过正。
【解决方案2】:

我知道这不是您问题的直接答案,但我宁愿建议使用 AutoHTML gem,而不是重新发明轮子:

auto_html 是一个 Rails 扩展,用于将 URL 转换为适当的 资源(图片、链接、YouTube、Vimeo 视频……)。这是完美的 如果您不想用丰富的 HTML 编辑器打扰访问者或 标记代码,但您仍然希望允许它们嵌入视频、图像、 您的网站上的链接和更多内容,纯粹是通过粘贴 URL。

https://github.com/dejan/auto_html

要直接回答您的问题,我认为问题在于您混淆了自动加载路径和查看路径。

你应该有

app.config.autoload_paths << app.root.join("lib/embeddable").to_s

append_view_path app.root.join("lib/embeddable/partials").to_s

【讨论】:

  • 谢谢!这可能是我应该做的。不过,我有兴趣学习构建自己的引擎和铁路,所以弄清楚如何解决我的问题会很棒!
  • 我尝试更改此设置,但是,路径最终位于包含 gem 的项目中,而不是实际 gem 的路径(并且找不到部分路径)。这就是我得到的:“/home/me/Arbeid/my_application/lib/embeddable/partials”。这就是我希望得到的:“/home/me/.rvm/gems/ruby-2.1.0/gems/my_gem/lib/embeddable/partials”
  • 哦,那你应该把它放在一个 gem 中。
  • 等等,我迷路了。您现在说的是 gem,但是您在原始问题中写的是 lib 中的一个模块。这是两个不同的东西,不是吗?
  • 哦,对不起。此处显示的所有代码均来自 gem。宝石是铁轨。所以 view_paths 被设置在 gem 中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多