例如,是否可以在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" %>');
}
由于
答案 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。
主要有两种方式:
public_folder
。get
路线投放。可能有一个宝石或其他东西要做(可能是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。
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。