Sinatra中的css.erb文件

时间:2013-03-20 21:16:47

标签: css ruby amazon-s3 sinatra assets

例如,是否可以在Sinatra中使用css.erb文件来提供来自AWS的图像。我从AWS中提取静态资产,可以在我的视图中提取图像,例如

<%= image_tag( aws_asset "/assets/img/banner2.jpg") %>

aws_asset是一个设置AWS网址的助手

helpers do
 def aws_asset( path )
 File.join settings.asset_host, path
 end
end

configure :development do 
 set :asset_host, "https://s3-eu-west-1.amazonaws.com/#{ENV['FOG_DIRECTORY']}" 
end

所以问题是如何从我的css文件中获取背景图像以从AWS中提取该图像

修改

当前设置

myapp.rb

get "/assets/css/style.css" do
erb :style 
end

layout.erb

<%= stylesheet_link_tag  "/assets/css/style.css"  %>

的style.css

body {
background: url('<%= aws_asset "/assets/img/banner1.jpg" %>');

}

由于

1 个答案:

答案 0 :(得分:3)

因为您已经使用了ERB:

body
{
  background-image:url('banner2.jpg');
}

会变成:

body
{
  background-image:url('<%= aws_asset "/assets/img/banner2.jpg" %>');
}

这是一个简单的答案。但是,既然您可能从AWS提供了相当多的文件,那么在您需要的所有不同位置使用帮助程序可能会让您感到厌烦,也很困难 - 也许您将来希望预编译CSS等等。使用Rack中间件隐藏一些实现是个好主意。

module MySinatraApp

  # A remote file called banner2.jpg would have the relative path
  # in the app of "/images/extra/banner2.jpg"
  # and on being requested, this middleware/app would check if
  # the remote file is in the list you've given
  # if it is, a 307 redirect is issued.
  # If it isn't, then a 404. Use with Rack::Cascade to pass on
  # to another app that may serve a local version of the file.
  # @example
  #   use RemoteImageServer, 
  #       :asset_host => "//s3-eu-west-1.amazonaws.com"
  #       :files      => ["banner2.jpg", "blah.gif"]
  class RemoteImageServer
    DEFAULT_OPTIONS = {
      subdir:        "images/extra",
      cascade:       false # until I work it out more, see note at bottom
    }

    def initialize(app,options={})
      app, options = app, DEFAULT_OPTIONS.merge(options)
      @asset_host = options[:asset_host]
      files = options[:files]
      @subdir = options[:subdir]
      @http_path_files = files.map{|file| File.join @subdir, file }
    end

    def call( env )
      dup._call( env ) # for thread safety
    end

    def _call( env )
      request = Rack::Request.new env
      if request.path_info.start_with? @subdir
        response = Rack::Response.new env
        if @http_path_files.include? request.path_info
          response.redirect File.join(@asset_host,request.path_info), 307
          response.finish
        else
          if @options[:cascade]
            response.status = 404
            response.finish
          end
        end
      else
        @app.call env
      end
    end
  end

  class MainApp < Sinatra::Base do
    # other stuff here…
  end

end

您可以使用此in the Sinatra Application,也可以使用rackup文件。我更喜欢后来的并使用Rack::Cascade

运行Rack :: Cascade.new([   MySinatraApp :: RemoteImageServer,   MySinatraApp :: MainApp])(我不确定在使用级联时如何最好地传递选项,我可能不得不考虑更多)。

  use RemoteImageServer, 
    :asset_host => "//s3-eu-west-1.amazonaws.com"
    :files      => ["banner2.jpg", "blah.gif"]
  run MySinatraApp::MainApp

这样远程主机“隐藏”在相对URL后面,您可以用本地文件替换远程文件,或者轻松更改远程提供程序。最后的Sinatra应用程序仍然可以从其公用文件夹中提供任何本地文件。但是,这段代码完全未经测试!可能有一个Rack中间件已经执行此操作(Rack Static Fallback可能已关闭)。


编辑:通过ERB提供CSS。

主要有两种方式:

  • 预编译CSS并通过public_folder
  • 提供
  • get路线投放。

预编译CSS

可能有一个宝石或其他东西要做(可能是Guard帮助器或其他东西),但这可以在控制台中使用:

require 'erb'
require 'tilt'
template = Tilt.new( "path/to/erb/file" )
File.open "app/public/stylesheets/main.css", "w" do |f|
  f.write template.render
end

由于编译后的CSS文件将驻留在Sinatra的公共目录中,因此它将作为静态文件提供。由于你已经从文件中获得了来自Sinatra的aws_asset助手,你需要稍微改一下,在运行之前重新定义控制台中的助手,或者对路径进行硬编码,或pass it a variable instead

从Sinatra get route

服务
get "/css/main.css" do
  erb :main # it will server main.erb from the views directory
            # and it will have access to helpers.
end

由于这是一个不会经常更改的文件,因此您最好添加cache control headers