Sinatra 资产管道,无法使其工作

Sinatra asset pipeline, can't make it work

我按照 Sinatra 的页面文档中的建议将 Sprockets 与 Sinatra 一起使用,但我无法使其正常工作。

当我转到 localhost:4567 时,页面加载正确但没有样式。如果我转到 localhost:4567/assets/app.css,我会收到一个未找到的错误。我想知道我缺少什么或者我使用 Sprockets 的方式有什么问题?

这是我的文件夹结构:

├── assets
│   ├── css
│   │   ├── app.css
│   │   ├── base.css
│   │   └── normalize.css
├── bin
│   └── app
├── lib
│   ├── app_assets.rb
│   └── main.rb
├── spec
│   ├── spec_helper.rb
│   └── main_spec.rb
├── views
│   └── index.erb
├── Gemfile
├── Gemfile.lock
├── Rakefile
├── .rspec
└── .ruby-version

app.css的内容是:

//= require normalize
//= require base

app_assets.rb的内容是:

module AppAssets

  def self.environment root_path
    environment = Sprockets::Environment.new root_path
    environment.append_path './assets/css/'
    environment

    # get assets
    get '/assets/*' do
      env['PATH_INFO'].sub!('/assets', '')
      settings.environment.call(env)
    end
  end

end

lib/main.rb的内容是:

require 'sinatra'
require 'sprockets'
require 'app_assets'

class Main < Sinatra::Base

  set :views, "#{settings.root}/../views"

  get '/' do
    erb :index
  end

end

文件 views/index.erb 包含行:

<link rel="stylesheet" href="assets/app.css">

bin/app的内容是:

#!/usr/bin/env ruby

$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')

require 'sinatra'
require 'sprockets'
require 'app_assets'

require 'main'
Main.run!

我 运行 输入:

$ bin/app

如有任何帮助,我们将不胜感激,我确定我做错了什么,但我看不出是什么。有人能看出来吗?

app_assets.rb 文件是这里的问题。当您在另一个文件中需要此文件时,不会自动包含您在该模块中定义的方法。您需要在需要 self.environment 方法存在的任何地方显式 include AppAssets

这里的第二个问题是 self.environment 不等同于 settings.environment。如果我理解正确,您要做的是在包含模块时定义资产路由。要实现这一点,一种方法是对模块使用 included 挂钩。每次在上下文中包含模块时,此挂钩都会得到 运行。如果使用它,app_assets.rb 中的代码将变为:

module AppAssets
  def self.included(klass)
    environment = Sprockets::Environment.new klass.settings.root

    # note the change to path. Since the file where this gets included
    # is inside a sub-folder, we need to traverse to one level above.
    environment.append_path '../assets/css/'
    klass.set :environment, environment

    klass.get '/assets/*' do
      env['PATH_INFO'].sub!('/assets', '')
      klass.settings.environment.call(env)
    end
  end
end

此挂钩的 klass 参数是包含此模块的 class。在我们的例子中,这是您在 main.rb 中描述的 Sinatra class。该文件看起来像:

class Main < Sinatra::Base
  include AppAssets

  # Same as what you have
end

有一篇关于在 Sinatra 中使用 Sprockets 的 Sinatra Recipes 文章:http://recipes.sinatrarb.com/p/asset_management/sprockets?#article