Rails资产管道中的静态html模板文件和开发模式下的缓存

时间:2012-08-24 20:52:12

标签: ruby-on-rails asset-pipeline

我正在使用AngularJS和Rails构建一个网站。我用于模板的HTML文件存储在/ app / assets / templates下,每次更新路径或更改模板内部嵌套部分内的内容时,我都需要“触摸”最高级别的文件。我正在改变的html文件的/ app / assets / templates目录。

因此,如果我有一个“edit.html”页面加载部分“_form.html”,那么每当我更新路线或更改_form.html中的内容时,我都需要确保触及edit.html。

这很烦人,非常挑剔。有没有办法通知资产管道/链轮以避免app / assets / templates目录的缓存?

6 个答案:

答案 0 :(得分:21)

我发现的最佳解决方案是不要将资源管道用于HTML模板文件。

而是创建一个名为TemplatesController的控制器,并仅创建一个操作。 然后使用以下路由将所有模板URL映射到该路径:

get /templates/:path.html => 'templates#page', :constraints => { :path => /.+/  }

然后将所有模板文件移至app/views/templates

然后在控制器内部设置以下内容:

caches_page :page

def page
  @path = params[:path]
  render :template => 'templates/' + @path, :layout => nil
end

这样,您的所有模板文件都将从控制器提供,然后将缓存到公共/模板中。为避免缓存问题,您可以创建模板路由的时间戳路径,以便使用版本传递缓存文件:

get '/templates/:timestamp/:path.html' => 'templates#page', :constraints => { :path => /.+/ }

这样,每次上传网站时都可以获得新的时间戳,并且可以将模板文件夹存储在任何您喜欢的位置。您甚至可以将模板文件夹存储在S3上,并为其设置资产URL。然后,只要模板文件被寻址,您就可以使用自定义资产方法:

templateUrl : <%= custom_asset_template_url('some/file.html') %>

其中:

def custom_asset_template_url(path)
  "http://custom-asset-server.website.com/templates/#{$some_global_timestamp}/#{path}"
end

然后只是将资产重定向到Rails服务器(如果找不到它),它将被生成。或者上传后可以预先生成所有模板文件。

答案 1 :(得分:6)

有很多(更多!)更好的方法来解决这个问题。

<%= path_to_asset("template_name.html") %>

这将从资产管道返回一个完全正常工作的文件,它可以使用ERB等。它没有文档,但它是链轮/资产管道的一部分。

答案 2 :(得分:3)

在我看来,这里需要做几件事:

  1. 模板应该是命名空间,因此人员模板会放在app / views / people / templates目录中
  2. 模板完全是静态的,因此不应该调用过滤器。
  3. 模板应该被缓存,使它们非常快。
  4. 这是使用Rails问题的可能解决方案:

    # Allows static content to be served from the templates
    # directory of a controller
    module HasTemplates
    
      extend ActiveSupport::Concern
    
      included do
        # Prepend the filter
        prepend_before_filter :template_filter, only: [:templates]
        # Let's cache the action
        caches_action :templates, :cache_path => Proc.new {|c| c.request.url }
      end
    
      # required to prevent route from baulking
      def templates;end
    
      # Catch all template requests and handle before any filters
      def template_filter
        render "/#{params[:controller]}/templates/#{params[:template]}", layout: 'blank'
        rescue ActionView::MissingTemplate
          not_found layout: 'blank'
        false
      end
    end
    

    请注意,我们将在前置过滤器中返回模板。这允许我们返回静态内容而不会遇到任何其他过滤器。

    然后你可以创建一个这样的路线:

    resources :people do
      collection do
        get 'templates/:template' => 'people#templates', as: :templates
      end
    end
    

    您的控制器变得简单:

    class PeopleController < ApplicationController
      include HasTemplates
    end
    

    现在可以从网址快速提供放置在/ app / views / people / templates中的任何文件。

答案 3 :(得分:1)

扩展RandallB的答案;这在资产管道的文档中明确提到:http://guides.rubyonrails.org/asset_pipeline.html

请注意,您必须将扩展名.erb附加到.coffee文件才能使其正常工作。 (例如,application.js.coffee.erb)

答案 4 :(得分:1)

您可以尝试使用gem js_assetshttps://github.com/kavkaz/js_assets)。

这允许您在javascript代码中运行asset_path,模拟类似的链接器方法。

答案 5 :(得分:0)

最干净的解决方案是使用ejs预编译您的html资源,并将其作为其他javascript文件提供。

  • 无http查询
  • 缩小
  • 将js数据传递给模板以使其动态化的可能性(ejs是来自下划线模板的端口,基本上 表现得像javascript的erb)

它基本上是这样的:

    #in you gemfile
    gem 'ejs'

    #in app/assets/javascripts/templates/my_template.jst.ejs
    <p>my name is <%= name %> !<p>

    #in your application.coffee
    #= require_tree ./templates

    JST['templates/my_template'](name: 'itkin')
    => '<p>my name is itkin !<p>'