sass-rails helpers “image-url”, “asset-url” are no

2019-01-21 11:05发布

问题:

I am on 3.2.1, with sass-rails-3.2.4 and sass-3.1.15...

The documentation for the asset pipeline says:

asset-url("rails.png", image) becomes url(/assets/rails.png)
image-url("rails.png") becomes url(/assets/rails.png)

...

So I made the following file:

# app/assets/stylesheets/public/omg.css.sass

body
  background: asset-url('snake.gif', image)

#lol
  background: image-url('snake.gif')

and when I visit localhost:3000/assets/public/omg.css I get:

body {
  background: asset-url("snake.gif", image); }

#lol {
  background: image-url("snake.gif"); }

... I also tried changing the file to omg.css.scss and changed the syntax to:

# app/assets/stylesheets/public/omg.css.scss

body {
  background: asset-url('snake.gif', image);
}

#lol {
  background: image-url('snake.gif');
}

but get the same results... does anyone have any idea why these helpers are not working?

回答1:

Despite what the documentation says, it seems the default options in rails 3.2.6 allow you to just make things work with even less path information in your CSS. E.g. ../app/assets/images/rails.png is references in your example.css.scss file with something like:

background: white url(rails.png) repeat-y;

You don't include the image-url or asset-url into your scss (as far as I know), just plain url(your_image.png). That bit of documentation appears to be just an explanation of what it is doing in the background.



回答2:

When I hit this problem, it was because I had not included the css file in the asset pipeline for pre-compilation. As a result, it would be generated at runtime. Because the sass-rails gem is commonly in the :assets group, the helpers are unavailable when generating css files at runtime.

Try adding the following line to your application.rb (or production.rb):

config.assets.precompile += %w( public/omg.css )

I found the fix on this post including a gotcha around naming the files when adding them to the precompiler.



回答3:

If you have updated your app to Rails 3.1 in the past, make sure you changed your application.rb file from

# If you have a Gemfile, require the gems listed there, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(:default, Rails.env) if defined?(Bundler)

to

if defined?(Bundler)
  # If you precompile assets before deploying to production, use this line
  Bundler.require *Rails.groups(:assets => %w(development test))
  # If you want your assets lazily compiled in production, use this line
  # Bundler.require(:default, :assets, Rails.env)
end

See this railscast on upgrading to Rails 3.1 and adding the asset pipeline.

Update: Rails 4 goes back to the old way of doing it. Thanks Aaron Gray!

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(:default, Rails.env)


回答4:

Have you enabled the asset pipeline in application.rb?

config.assets.enabled = true

You did right by setting the extension on your Sass stylesheets to .css.scss. That lets Rails know to parse the file with Sass first before it emits the content as CSS.



回答5:

You might want to try clearing /tmp/cache. I am too new to Rails and Sass to know why this worked, but it solved the same problem for me after hours of searching.

BTW, this worked despite the fact that I could see other Sass directives, such as setting variables and calculating with them, being executed. I'm sure there is a very simple explanation, once I have time to track it down.



回答6:

I made the change suggested by @Ryan, as well as upgrading sass-rails:

bundle update sass-rails

sass 3.2.6 worked for me, while 3.2.5 did not.



回答7:

We just had the same problem and fixed it by explicitly requiring sprockets in the Gemfile (even though it's a dependency of ActionPack):

group :assets do
  gem 'sprockets'
  gem 'sass-rails', '~> 3.2.3'
  # ...
end

I don't know why, but it works now. ;-)



回答8:

I've been banging my head against this for days. The only solution that worked for me was as follows:

  1. Make sure sass-rails to your :development group in your Gemfile.
  2. If that doesn't fix it, add the following to a new file in config/initializers/ called something like "horrible_sass_patch.rb":

    begin
      require 'sass-rails'
    rescue
    end
    
    if Class.const_defined? "Sass::Script::Functions"
      module Sass::Script::Functions
        # This function exists, but doesn't automatically register
        declare :asset_url, [:value]
        declare :image_url, [:value]
        declare :font_url, [:value]
        # ... etc
      end
    end
    

Note: This requires that you are using the "active" Bundler loading mechanism, i.e. your application.rb uses the following:

Bundler.require *Rails.groups(:assets => %w(development test))

... and if your stylesheets are in vendor, make sure they're included in Sass's configuration:

if config.respond_to? :sass
  config.sass.load_paths << Rails.root.join('vendor', 'assets', 'stylesheets')
end


回答9:

You can just add a trailing forward slash / to the path and use url like you usually do.

background-image: url("/assets/rails.png")