通过链轮动态渲染sass文件

els*_*gav 5 ruby-on-rails sass sprockets

我希望,从帮助器中,在.scss.erb使用image-url()sass函数的模板中呈现一些变量:

// template.scss.erb

#<%= id %> {
  background-image: image-url('<%= image_file %>');
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,ERB部分很简单:(
利用此堆栈溢出答案)

vars_binding = OpenStruct.new(
                 id:         'foo', 
                 image_file: 'foo.jpg'
               ).instance_eval { binding }

template = File.read('path/to/template.scss.erb')

rendered_sass = ERB.new(template).result(vars_binding)
Run Code Online (Sandbox Code Playgroud)

运行该代码sass现在等于:

#foo {
  background-image: image-url('foo.jpg');
}
Run Code Online (Sandbox Code Playgroud)

但是,当我下次尝试运行时:

css = Sass::Engine.new(
  rendered_sass,
  syntax:     :scss,
  cache:      false,
  load_paths: view_context.assets.paths,
  read_cache: false,
  style:      :compressed
).render
Run Code Online (Sandbox Code Playgroud)

它回来了

NoMethodError: undefined method `[]' for nil:NilClass
from …/sprockets-3.2.0/lib/sprockets/sass_processor.rb:267:in `sprockets_context'
Run Code Online (Sandbox Code Playgroud)

因为调用Sass::Engine不提供Sprockets上下文.

如果我image-url().scss.erb模板中删除,并将其替换为本机url(),它将正确呈现为CSS,没问题.

那么如何在sprockets上下文中呈现此模板呢?

els*_*gav 8

在深入研究类似的问题,以及大量的反复试验之后,我找到了解决方案:我必须:sprockets在调用时提供哈希值Sass::Engine.new.

css = Sass::Engine.new(
  rendered_sass,
  syntax:     :scss,
  cache:      false,
  load_paths: view_context.assets.paths,
  read_cache: false,
  style:      :compressed,

  # The key ingredient…
  sprockets:  {
    context:     view_context,
    environment: view_context.assets
  }
).render
Run Code Online (Sandbox Code Playgroud)

应该注意的是,它view_context是从视图文件传递的,但也可能是ActionView::Base.new