Rails / Sass: Import file from the vendor folder - ruby-on-rails

I have a stylesheet app/assets/website/base.scss that starts with:
#import "bootstrap-select.min.css";
The bootstrap-select.min.css file exists in the vendor/stylesheets/ folder. When I try to access it in production, I get a 404:
"NetworkError: 404 Not Found - http://mysite.herokuapp.com/assets/bootstrap-select.min.css"
(It works fine on my development rig though.)
Here's what I've tried so far:
Tried using #import asset-path("bootstrap-select.min.css"). Got a syntax error (apparently asset-path doesn't work with imports).
Tried adding config.assets.precompile += %w(bootstrap-select.min.css) to config/environments/production.rb
Any idea why this might be happening?
Rails 4.0.4 / Ruby 2.1.2

Ended up changing it from bootstrap-select.min.css --> bootstrap-select.min.scss ..
It worked!
Sass actually places the contents of .scss files in place - With .css files it just links to the file with an #import, which is why it wasn't working (thanks #cimmanon!)

Actually, you could just remove .css suffix from #import "bootstrap-select.min.css"; Sass expects from you just the name of the assets and is smart enough to look in all possible asset placements and import whatever it can import (so the name should be format-independent)

Related

Rails Asset Pipeline with sass #imports [duplicate]

This question already has answers here:
Import regular CSS file in SCSS file?
(15 answers)
Closed 7 years ago.
I'm using Rails 4.2.
In my rails project directory, I have a frontend directory:
/railsproject/frontend
/railsproject/frontend/styles
/railsproject/frontend/styles/main.scss
/railsproject/frontend/styles/variables.scss
/railsproject/frontend/node_modules/normalize.css/
/railsproject/frontend/node_modules/normalize.css/normalize.css
(I know it's unusual to have a directory with a period in it, but I have tried changing the directory name and corresponding #import statement and it didn't make a difference)
I have added config.assets.paths << Rails.root.join("frontend","styles") to application.rb.
In /railsproject/app/assets/stylesheets/application.css:
#import "main.scss";
Everything is good so far, it loads/processes the main.scss file.
In /railsproject/frontend/styles/main.scss
#import 'variables'; // this works fine
#import '../node_modules/normalize.css/normalize.css'; // this does NOT work
The second import doesn't work...I get a GET error in the Chrome console, and the rails server says:
Started GET "/node_modules/normalize.css/normalize.css" for ::1 at 2015-07-02 15:55:38 +0800
ActionController::RoutingError (No route matches [GET] "/node_modules/normalize.css/normalize.css"):
What am I doing wrong?
SASS is not letting you import CSS files, it wants SCSS files to compile into CSS.
Either switch your file extension to SCSS or upgrade to SASS 3.2.10 which is supposed to let you import CSS files.
Reference: Import regular CSS file in SCSS file?

How to import SCSS mixins in a Rails app?

Trying to figure out how to import some SCSS files in a Rails 4 app. The files are:
#import "shared/mixins",
"shared/reset",
"shared/about-light";
I'm not sure how to do this properly and I don't know how to set the path either.
I put these files in a folder called "shared" and I put this folder inside of /lib/assets/css/ Is this the right way to do it?
Also tried to put the files in /vendor/assets/stylesheets/
How do I properly import these files?
Error:
File to import not found or unreadable: mixins.
Load paths:
We typically put mixins in a partial file called _mixins.scss directly in the app/assets/stylesheets/ directory, possibly under a subdir like shared if you want more organization. In your application.css you can then do (as you did)
#import 'shared/mixins';
#import 'shared/colors';
or whatever. If you really want them to sit somewhere else, you should look into the load_paths configuration setting for SASS. You can tell SASS where to look when it's importing files and probably lib/assets and vendor/assets are not included by default.
To add this configuration, in your environment.rb or other config file, you can do something like
config.sass.load_paths << File.expand_path('../../vendor/assets/stylesheets/')
which will make SASS look in vendor/assets/stylesheets in addition to all the other directories it searches in by default.
I think you are confusing partials and mixins.
From the Sass documentation:
Mixin
"A mixin lets you make groups of CSS declarations that you want to reuse throughout your site. You can even pass in values to make your mixin more flexible. You can think of a mixin like a function for css (awesome right!)." More about mixins here.
Partial
"You can create partial Sass files that contain little snippets of CSS that you can include in other Sass files. This is a great way to modularize your CSS and help keep things easier to maintain. A partial is simply a Sass file named with a leading underscore." More about partials here.
Therefore, what you are attempting to import are indeed partials and should be prefaced with an underscore.
Your directory structure should look like this:
assets
stylesheets
application.css.scss
shared
_mixins.scss
_reset.scss
_about-light.scss
And your application.css.scss file should look like this:
#import "mixins";
#import "rest";
#import "about-light";
Ok so I was able to work this out as follows:
In application.rb add the following:
config.sass.load_paths << File.expand_path('../../vendor/assets/stylesheets/')
In the CSS file import as:
#import "mixins",
"reset",
"about-light";
Put the files in to:
/vendor/assets/stylesheets/
Restart the server.

Sass variable undefined during Rails asset precompile

I have several dozen sub directories in my stylesheets folder, many of which refer to each other with variables defined in the file _settings.sass. In my application.sass file, I importing settings first:
#import "settings"
#import "folder-one/some-sass-file"
#import "folder-two/some-other-sass-file"
This works well in development, but when I try to precompile, I get an error about $namespace being undefined in "folder-one/some-sass-file"--even though it's defined right there at the top in _settings.sass.
This seems to be happening because the compiler is trying to compile everything in sequential order, rather than looking at application.sass. Am I understanding this right? And if so, what can I do to remedy the problem?
You just need to add #import "settings" into your some-sass-file. Asset pipeline will minify it for you so there is no problem.

SCSS import relative to an imported stylesheet?

I've installed foundation-rails in my Rails app and run rails g foundation:install. The project-specific file(s) (mostly foundation_and_overrides.scss) are properly installed. The gem is there and it had no trouble installing, and the dependencies (SASS, Compass) are also there. But I'm getting:
Error compiling CSS asset
SASS::SyntaxError: File to import not found or unreadable: global.
Originating from:
/Users/local/.rvm/gems/ruby-2.0.0-p353/gems/foundation-rails-5.0.2.0/vendor/assets/stylesheets/foundation/components/_accordion.scss:1
After investigating, I've discovered that _accordion.scss was #imported in the main foundation.scss file, located two directories up in stylesheets/:
#import 'foundation/components/accordion'
The "missing" file, _global.scss, meanwhile, is in that same directory. If I then change the #import code in _accordion.scss from #import 'global' to #import 'foundation/components/accordion', it clears and moves on to the next error (there are a lot of sub-imports here).
It's clear that what's happening is SASS is looking for _global.scss relative to the top stylesheet, foundation.scss, and not relative to the imported stylesheet asking for it (_accordion.scss).
I can't imagine this is a bug in Foundation/Foundation-Rails – this gem wouldn't work for anyone – and I don't want to modify the gem's contents myself.
So my question: do I have to change some SASS settings to allow #import relative to an imported stylesheet? I don't want to modify this gem to make it work (I'd like to allow for future updates to the gem).
Edit
Clarification of directory structure within the gem's vendor/assets/stylesheets directory:
foundation.scss
foundation/components/_accordion.scss
foundation/components/_global.scss
Edit 2
You can actually see the gem's code and structure on github
Edit 3
Thought I'd solved the problem, but I didn't: changing from an #import to a =require got rid of the errors, and included Foundation's CSS. But require does not import the SCSS functionality - variables, mixins - that Foundation provides. There's no way to change global values this way, or to retrieve them or the mixins from the main stylesheet or other #imported stylesheets.
It looks like Foundation thinks this is the best possible solution:
Manually add Foundation's stylesheet subdirectories (each of them) to SASS's :load_paths in the main block of application.rb:
config.sass.load_paths += [
"#{Gem.loaded_specs['foundation-rails'].full_gem_path}/vendor/assets/stylesheets/foundation/components",
"#{Gem.loaded_specs['foundation-rails'].full_gem_path}/vendor/assets/stylesheets/foundation/"
]

Rails assets:precompile strange behavior

I found myself in front of a strange behavior of the assets:precompile task, or at least in front of something I don't fully understand.
So, I am using Rails 3.1.3, Sprockets 2.0.3, Less 2.0.11 for my web application, plus I rely on Bootstrap for the layout, so I am using also less-rails 2.1.8 and less-rails-bootstrap 2.0.8.
I have customized the style like they say here.
The configuration of my assets is:
stylesheets
|--application.css.scss
|--custom-style/
|--variables.less
|--mixins.less
|--buttons.less
|--custom-style.css.less
In application.css.scss I do
//=require custom-style
And in custom-style I do
#import "twitter/bootstrap/reset";
//#import "twitter/bootstrap/variables"; // Modify this for custom colors, font-sizes, etc
#import "custom-style/variables";
//#import "twitter/bootstrap/mixins";
#import "custom-style/mixins";
// And all the other standar twitter/bootstrap imports...
// Other custom-style files to import
#import "custom-style/buttons"
//...
// And other rules here
//...
Finally in buttons.less I use some variables and mixins defined in the variables.less and mixins.less Bootstrap files, #white and .buttonBackground to be more specifc.
If I launch bundle exec rake assets:precompile with the above configuration, the task fails and I get this error:
$ bundle exec rake assets:precompile
/usr/local/rvm/rubies/ruby-1.9.3-p0/bin/ruby /usr/local/rvm/gems/ruby-1.9.3-p0/bin/rake assets:precompile:all RAILS_ENV=production RAILS_GROUPS=assets
rake aborted!
.buttonBackground is undefined
But is that if I do this changes
buttons.less --> buttons.css.less
#import "buttons" --> #import "buttons.css.less"
Everything works fine!!
Is it something related to the scope of less variables and functions when working with nested imports? Or something that has to do with the order the less parser, or Sprockets, processes the import tree?
Am I missing something or doing something in the wrong way?
Thanks :)
Note: I get the error even with the original variables and mixins files, so it's not connected with the overrides done into them.
I can think of one of two possibilities right now:
1) You should change application.css.scss to application.css.less and use:
#import "custom-style";
instead of the sprockets //= require ...
2) The LESS compiler is very finicky about its semicolons. I noticed that you have
#import "custom-style/buttons" - it should be #import "custom-style/buttons";
Dunno if the issue is really that simple, but it's a start.
Have you tried renaming the file to buttons.css.less but keeping the extension off the #import (i.e., #import "buttons")?
That's how I do it with SCSS and it works fine.
Another thought is to replace the //=require custom-style in application.css.less with an #import "custom-style" directive. The Rails Guide here recommends using #import (which is processed with SCSS/LESS) are over //=require (which is processed with Sprockets):
If you want to use multiple Sass files, you should generally use the Sass #import rule instead of these Sprockets directives. Using Sprockets directives all Sass files exist within their own scope, making variables or mixins only available within the document they were defined in.
This doesn't really answer your question, but is the only reason you are mixing sass and less to use twitter bootstrap? If you prefer to use just sass, there are some bootstrap gems where the authors convert the less to scss, like bootstrap-sass. Before I wasted too much time trying to juggle both in a project, I'd completely buy into one or the other, but that's just my opinion.

Resources