#import-ed .scss files and Sprockets 4 - ruby-on-rails

This is maybe too early to get good answers, but here we go: I have a test Rails project, with assets/ directory that looks something like this:
config/
manifest.js
images/
javascripts/
application.js
stylesheets/
_base.scss
_reset.scss
_theme.scss
_variables.scss
application.scss
The manifest file looks like this:
// JS and CSS bundles
//= link_tree ../javascripts .js
//= link_tree ../stylesheets .css
// Images so that views can link to them
//= link_tree ../images
And the application.scss like this:
#import "reset";
#import "variables";
#import "base";
#import "theme";
_base.scss and _theme.scss both make use of variables defined in the _variables.scss file.
What I want it to do is just compile application.scss as normal, but it fails because it doesn't think the variables are defined; this is reasonable, I'm linking as a tree, so [I assume] it's compiling each file individually, and the variables are not available to the two files at that point in time.
So I try link ../stylesheets/application.css instead of the tree, and I get the error message couldn't find file '../stylesheets/application.css' under '/Users/danielcouper/Projects/myproject/app/assets/config'; ie it seems to be looking in entirely the wrong place, or there are different (undocumented) rules regarding filepaths depending on whether you use link or link_tree.
If I move manifest.js out from the assets/config/ directory to assets/ to get the relative paths working, as described in the Sprockets upgrading notes, I get an error telling me that there is no manifest file under assets/config/.
The documentation is [understandably] super sparse at the minute; the only useful thing I've read was at http://eileencodes.com/posts/the-sprockets-4-manifest/, which allowed me to get to this point

Don't use link_tree, link tree will import all the files in the tree. If you only want one application.css file use this:
link application.scss
This way sprockets will start at that file and sass will do the imports.

Related

Bug on url() in scss files on rails 7

I'm having troubles with the url() css function in my rails 7 project. I reproduced it on a brand new one: https://github.com/paul-mesnilgrente/rails-7-url, see this commit: https://github.com/paul-mesnilgrente/rails-7-url/commit/77e1379cd98827f43b02605852220cd3db93ce06
It uses sass (see package.json) with cssbundling-rails and sprockets-rails. If you look at the app/assets/stylesheets/application.sass.scss, I have: background-image: url('images/background.jpg'). And the background.jpg file is app/assets/images/background.jpg.
I tried several paths to include that background (../images/background.jpg, /images/background.jpg etc.) but nothing works. The compiled result in the development environment should have a digest hash appended to it but there's nothing and the path is only translated to /images/background.jpg which gives a 404. This makes me thing that sprockets doesn't find the background image so it doesn't "compile" that path.
Any ideas of what I'm doing wrong?
I found the problem which was actually pretty dumb. In manifest.js we have this line by default //= link_tree ../images.
And the thing is, rails doesn't look for the assets relatively to your stylesheet or even relatively to app/assets. It's only relative to those //= link_tree ... paths.
So the right path, which I hadn't tried before was url("background.jpg").
Side note : If you use libraries like datatables which are including relative paths, you need to add something link this in manifest.js //= link_tree ../../../node_modules/datatables.net-zf/css

Using Bootstrap SASS w/Rails 5 without a gem

I had no luck with the official TBS gem.
Instead, I've installed all of the required .js and .scss files in my vendor directory.
in my applications.css.scss, I have...
#import "bootstrap/scss/bootstrap";
#import "historical-bs-custom";
the other SASS files are also within the /scss directory above.
These are the components I thought would get loaded by the #import statements in the main bootstrap.scss by default. Ex. _alert.scss, _badge.scss, etc.
in my application.js, I have...
//= require rails-ujs
//= require turbolinks
//= require jquery-3.3.1.slim.min
//= require popper.min
//= require bootstrap/bootstrap
//= require_tree .
Seen in source code view of the page, .js loads fine, but my CSS does not at all.
My gemfile specifies that it is using
gem 'sass-rails', '~> 5.0'
I thought this would be enough to preprocess the SASS. I also added the
# Bootsrap sass specific gem
gem 'bootstrap-sass'
but had no luck.
I was hoping to be able to use SASS variables along with custom CSS rules for this application. Most of the documentation on the internets relates to gem usage, which I found I was not the only one having trouble with.
Anyone out there trying to do such a thing without a gem?
Any advice or insight would be greatly appreciated.
Thanks in advance.
I was able to get the SASS to preprocess by amending the code as seen below, using the #import statements outside of the initial default commenting that are in application.css.scss files.
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
* vendor/assets/stylesheets directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
* files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope.
*
*/
#import "bootstrap/scss/bootstrap";
#import "historical-bs-custom";
#import "test";
At first, when using VSCode, I got bad syntax highlighting, so I backed off. A very nice coworker and friend had me try this again. Now I can get on with my life.

How should I go about managing sass code when using bootstrap-sass?

The documentation says:
Import Bootstrap styles in app/assets/stylesheets/application.scss:
// "bootstrap-sprockets" must be imported before "bootstrap" and "bootstrap/variables"
#import "bootstrap-sprockets";
#import "bootstrap";
bootstrap-sprockets must be imported before bootstrap for the icon fonts to work.
Make sure the file has .scss extension (or .sass for Sass syntax). If you have just generated a new Rails app, it may come with a .css file instead. If this file exists, it will be served instead of Sass, so rename it:
$ mv app/assets/stylesheets/application.css app/assets/stylesheets/application.scss
Then, remove all the //= require and //= require_tree statements from the file. Instead, use #import to import Sass files.
Do not use //= require in Sass or your other stylesheets will not be able to access the Bootstrap mixins or variables.
But if I do as they say, my other stylesheets won't be included automatically, as they did before that. Should I include every stylesheet explicitly in layout? AFAIU, that would also make me have separate stylesheets in production environment, instead of one as it would have been without bootstrap-sass.
There are several things here. First, by default each stylesheet is served in separate http request in development, and in one request in production (they are precompiled into one file). If we follow the docs, we'll end up having one request in development as well, which would negate performance benefit of compiling only the file that has changed. If we don't, we might end up having bootstrap several times in our stylesheets. In case we need some variables or mixins in several stylesheets.
So I suggest having it this way:
application.sass (do note that I put require_self before require_tree .):
/*
*= require_self
*= require_tree .
*/
// import bootstrap once
#import "bootstrap-sprockets"
#import "bootstrap"
.d1
text-align: center
welcome.sass:
// in other files import only some particular partials
#import "bootstrap/variables"
#import "bootstrap/mixins"
.d2
text-align: right
But if I do as they say, my other stylesheets won't be included automatically, as they did before that.
Yes, you a right.
1) You shouldn't remove your require directives from application.scss. They don't want to use require directives because in this case you don't have ability to use SASS variables and mixins inside of included files.
2) Just rename application.css to application.scss. They want it because in this case you will have ability to use #import directives inside application.scss file. This is mean that you will have ability to use SASS variables and mixins inside of included files.
Should I include every stylesheet explicitly from layout?
No, just leave them in application.scss
AFAIU, that would also make me have separate stylesheets in production environment, instead of one as it would have been without bootstrap-sass.
No, you will use one application.scss in different environments.

How to make Rails not import every file from app/assets/stylesheets?

In app/assets/stylesheets, I have many sass files. In a requested page, every file in app/assets/stylesheets is imported (with a tag). How do I make it so that not every file from the directory is imported, but only the ones that I pick?
Note: I'm running Rails 4.1.2
You change your app/assets/stylesheets/application.css file.
Instead of *=require_tree .
Add:
*=require './file1'
*=require './file2'
...
You don't need to supply .css or .css.scss
Manifest
As alluded to by #Ruby Racer, you'll be looking to manipulate the manifest of your stylesheets in your application:
Sprockets uses manifest files to determine which assets to include and
serve. These manifest files contain directives - instructions that
tell Sprockets which files to require in order to build a single CSS
or JavaScript file.
The way to use this is at the top of any of your css files, typically your application.css file -
/app/assets/stylesheets/application.css
/* = require "file" */
By doing this, you'll be able to build your stylesheet assets as you require
--
SASS
If it's only the stylesheets you want to change, you need to remember something else -
If you changed the extension of your CSS to .css.scss, you'll be able to call the #import function of SASS to create a similar effect to the manifest functionality:
#app/assets/stylesheets/application.css.scss
#import "file"

How to use the add_import_path Compass configuration function

I'm trying to have some global partials from another compass project imported into a new compass project. I've found the add_import_path function that looks like it could be the answer.
I have defined an add_import_path in my config.rb but how do I import the partials in that directory?
ie:
IN CONFIG.RB
add_import_path "path/to/other/project/";
IN MY STYLE.SCSS
#import "grid";
#import "tyography";
#import "a partial from the other project"??
I can't find anything in the compass documentation on how to import from the import path. I get a compile error saying:
Syntax error: File to import not found or unreadable: test.
You need to take the actual files, the filename.css.scss files from the stylesheets folder, copy them, and put them into the stylesheets folder of your new project.
You can get css files from anywhere inside your app by adding them to the top of the application.css file, the part that looks like this:
/* ...
*= require_self
*= require_tree .
*/
But they should be inside your project folder somewhere.
Check out the docs here: http://guides.rubyonrails.org/asset_pipeline.html

Resources