例如,是否可以在 Sinatra 中使用 css.erb 文件来提供来自 AWS 的图像。我正在从 AWS 中提取我的静态 Assets ,例如可以在我的 View 中提取图像
<%= image_tag( aws_asset "/assets/img/banner2.jpg") %>
aws_asset 是设置 AWS url 的助手
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 中提取该图像
编辑
当前设置
我的应用.rb
get "/assets/css/style.css" do
erb :style
end
布局.erb
<%= stylesheet_link_tag "/assets/css/style.css" %>
样式.css
body {
background: url('<%= aws_asset "/assets/img/banner1.jpg" %>');
}
谢谢
最佳答案
因为您已经为此使用了 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
可能有 gem 或其他东西可以做到这一点(可能是 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 的公共(public)目录中,因此它将作为静态文件提供。由于您在文件中获得了来自 Sinatra 的 aws_asset
帮助程序,因此您需要稍微更改它,或者在运行之前在控制台中重新定义该帮助程序,或者对路径进行硬编码,或者 pass it a variable instead .
从 Sinatra get 路由提供服务
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 .
关于Sinatra 中的 css.erb 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15534896/