9

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

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

这很烦人而且非常挑剔。有什么方法可以通知资产管道/链轮以避免缓存 app/assets/templates 目录?

4

6 回答 6

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

这样,您的所有模板文件都将从控制器提供,然后将缓存到 public/templates 中。为避免缓存问题,您可以在模板路由中创建时间戳路径,以便您的缓存文件随版本一起交付:

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 服务器并生成它。或者所有模板文件可以在上传后预先生成。

于 2012-08-29T14:56:32.590 回答
6

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

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

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

于 2013-02-24T01:28:39.573 回答
3

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

  1. 模板应该是命名空间的,所以人员模板进入 app/views/people/templates 目录
  2. 模板是完全静态的,因此不应调用之前的过滤器。
  3. 模板应该被缓存,使它们非常快。

这是使用 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 中的文件都可以通过 url 快速提供。

于 2014-10-20T16:08:47.157 回答
1

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

请注意,您必须将扩展名 .erb 附加到您的 .coffee 文件才能进行这项工作。(例如,application.js.coffee.erb)

于 2013-08-17T02:52:30.910 回答
1

您可以尝试 gem js_assets( https://github.com/kavkaz/js_assets )。

这使您可以asset_path在模拟类似链轮方法的 javascript 代码中运行。

于 2013-09-26T14:51:46.237 回答
0

最简洁的解决方案是使用 ejs 预编译您的 html 资产并将它们作为其他 javascript 文件提供。

  • 没有http查询
  • 缩小
  • 可以将 js 数据传递给您的模板以使它们动态化(ejs 是下划线模板的一个端口,基本上表现得像 erb for javascript)

它基本上是这样工作的:

    #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>'
于 2015-11-28T03:53:32.557 回答