Using a Rails Engine to share SASS Mixins across projects - ruby-on-rails

I am trying to build a Rails Engine which serves assets to its host application. Specifically, I would like to be able to do the following:
# Host App's Gemfile
gem 'my-rockin-engine'
And ...
# Host App's application.css
/*
*= require styles
*/
#import 'my-rockin-engine/mixins'
And ...
# Host App's style.sass
.host-app-defined-class-name
+my-rockin-engines-mixin
Where the mixin "my-rockin-engines-mixin" is defined somewhere in the assets of MyRockinEngine.
The problem
I have a chain of #imports from the host app, through the engine. (I'm using #imports due to reasons described here.) Any style definitions that I create inside the Engine's assets are available to the host app. However, none of the SASS mixins I create are available anywhere other than in the same file that the mixin is defined in.
Essentially, I'm wondering if my implementation is not working because either (1) I'm using Engines in a confused way; (2) It is not possible to share mixins between Rails Engines and their host application; (3) There is some aspect of sprockets/rails/compass/sass (#import/require) directives that I am misunderstanding.
Any help would be greatly appreciated! And I can always offer further details should anyone need them.

For posterity, it seems the problem I was having was in the realm of (3) -- described in my question.
Don't try and #import sass files which are named foobar.css.sass. Compass will treat such files as css, since they have to be imported via #import 'foobar.css'. #import foobar will fail because the .css is part of the filename.
So, my problem is solved by ensuring any files I #import use the .sass extension, and don't have .css in the last part of the file name.

Related

using Bourbon with wagon ( Locomotive CMS )

Is it some possible way to make work Bourbon with wagon of Locomotive CMS ?
I added a bourbon and neat gems to Gemfile of wagon but after bundle install and starting server i got this :
File to import not found or unreadable: bourbon.
Load paths:
/Users/alex/workspace/locomotive-test/public/stylesheets
/Users/alex/.rbenv/versions/1.9.3-p392/lib/ruby/gems/1.9.1/gems/compass-0.12.2/frameworks/blueprint/stylesheets
/Users/alex/.rbenv/versions/1.9.3-p392/lib/ruby/gems/1.9.1/gems/compass-0.12.2/frameworks/compass/stylesheets
Compass::SpriteImporter
I have found that getting Locomotive to work with Bourbon (or Susy or any addon SASS gem) is a two-stage problem. First, the resources must be loaded correctly in the Wagon gemfile, and then they must be #imported in every dependent file to compile correctly when pushed to the Engine.
To get Bourbon to import correctly into Wagon (1.5.1), add Bourbon to the gemfile in the :misc group per the sample pattern:
group :misc do
# Add your extra gems here
gem 'bourbon', require: 'bourbon'
end
Then, just run $ bundle install and it should work fine. I found that I didn't need to do $ bourbon install and have the actual .css files in my public/stylesheets folder. The gem was enough for my Wagon instance.
Pushing the site to Engine, however, can prove tricky. Wagon will compile the SASS files in an arbitrary order on push (reference: LocomotiveCMS Google Group). Consequently, the best DRY rails practice of having all your #import calls in one main sass file, and referencing only that file in a top-level application.css file won't work here:
./public/stylesheets
-application.css #requires self and main
-main.scss #imports all other stylesheets, normally where we'd #import 'bourbon'
/other_stylesheets
-variables.scss
etc. etc.
On push, Wagon won't understand that main.scss #imported Bourbon ahead of all other resources. So, it will usually fail with 'undefined mixin...'
To solve that, I still put variables.scss, mixins.scss, etc. in a folder (./public/stylesheets/base/ for instance) and call #import for those resources on every page specific stylesheet (posts.scss, etc.). In addition, any stylesheet that uses a Bourbon, Neat, Susy, whatever mixin has to call #import on that gem reference and the mixins and the variables... it has to be repeated in each dependent sheet.
./public/stylesheets
-application.css # requires self and main
-main.scss # imports all other stylesheets, normally where we'd #import 'bourbon';
/other_stylesheets
-variables.scss # might #import 'font-awesome';
-mixins.scss # #import 'bourbon'; #import 'variables';
etc. etc.
Unfortunately, this is NOT very DRY coding. In fact, there's probably a lot of bloat and redundancy that can be eliminated. So far, it's the most reliable method I've found for pushing my Wagon site to the Engine using these gems. That being said, if you're looking for a quick fix, rather than identifying each resource to #import for each page, you could make an import.scss stylesheet that calls Bourbon, Neat, what-have-you and just #import that import.scss resource into every other sheet.
The final catch (famous last words!), is that the Engine won't accept .scss or .sass files, despite the documentation. Pre-processor stylesheets have to be prepended with .css:
main.scss => main.css.scss
Otherwise, the Engine kick back an error "you are not allowed to upload..."
Hope that helps!
UPDATE:
I realized a couple weeks after posting this that the reason for the Sass troubles in Locomotive vs. other Rails apps: I was using old sprockets syntax in my application.css file.
So, the best method is to make as many Sass sheets partials as possible (prepend your filenames with an underscore -> _example.css.scss). Then, change the application.css to a Sass sheet -> application.css.scss. Finally, don't use any *= require calls like we used to with Sprockets. Instead, we can and should use the Rails best practice of Sass #import calls. You can even glob your partials in subfolders, if so inclined. The reason is, Locomotive installs sass-sprockets and sass-rails gems by default. These gems enable #import in the application.css.scss file with sprockets/asset pipeline. By using Sass partials for subsequent stylesheets, the compilation for application.css.scss will have its own domain and call the partials into it, instead of compiling each subsequent sheet in its own domain. Otherwise, you would probably see wagon push failing with 'unknown mixin...' on the first sheet outside of the main application sheet. If you order your partials in the correct order of dependency (which file does every sheet need? That goes first...), this method also has the added benefit of keeping your compiled application stylesheet very DRY.
Cheers!

How do I make a Bootstrap sass variable visible to another imported sass file?

I am using bootstrap-sass in a Rails application. So far, everything has worked fine, but I have just tried to import another third-party sass file that uses bootstrap variables and it cannot see them.
In my application.css.scss
*= require bootstrap_local
In bootstrap_local.css.scss
#import "bootstrap";
#import "bootstrap-social";
When I do a page access, I get a Rails error
Undefined variable: "$line-height-computed".
(in .../app/assets/stylesheets/bootstrap-social.scss:11)
The variable needed by bootstrap-social.scss is defined in the previously imported bootstrap file (in fact it's defined in a partial bootstrap/variables that it includes).
As far as I understand, this should work because bootstrap_local is required, which means that everything in it is compiled together in one scope, so everything imported into bootstrap_local is treated as being one large file. Perhaps I have this wrong?
If I throw an #import "bootstrap"; into bootstrap-social.scs then it works fine. But I should not need to do this, so I either doing something wrong or I there is some misconfiguration with my setup.
What do I need to do to fix this?
Gems:
bootstrap-sass-3.1.1.1
sass-rails-4.0.3
System:
Rails 4.0.1
ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-linux]
(Bootstrap Social is a set of social sign-in buttons made in pure CSS based on Bootstrap and Font Awesome.)
The problem described in the question can be resolved by changing the application.css.scss manifest to use import instead of require:
#import "bootstrap_local";
It is also necessary to remove any require_tree . from the manifest because it would otherwise require the same bootstrap_local file because it lies in its path.
On reflection, not having require tree . in the manifest is probably wise because it prevents unwanted files from being included. I only had it there because it's there by default in a new Rails project (the same goes for require_self; it's cleaner not to put that in the manifest).
In reference to the suggestion about prefixing the file with an underscore, this is a good thing to do when the you don't need file, like bootstrap-social in the question, to be a compiled into a separate CSS file. So, I did end up renaming it to _bootstrap-social.scss.

How to edit twitter bootstrap files in rails?

I'm trying to find the twitter-bootstrap files in my rails app ('bootstrap-sass', '2.0.0'), as I need to make a change directly to the bootstrap-responsive.css file, however, I can't find it.
I have bootstrap up and running, but can't seem to find the bootstrap files. How do I locate the bootstrap-responsive.css file?
Thank you!
The bootstap-sass gem uses the Rails 3.2 asset pipeline to inject the necessary stylesheets into your app. The actual stylesheet files are located in the gem installation directory, not in your project itself.
Depending on what you want to change, you can either:
Copy the _bootstrap-responsive.scss file from the gem into your app/assets directory and edit it there.
Customize the necessary Bootstrap variables before loading up Bootstrap in your application.scss file:
$btnPrimaryBackground: #f00;
#import "bootstrap";
Edit: Try looking under
app/assets/stylesheets
Here's an example
https://github.com/joliss/solitr/tree/master/app/assets/stylesheets
I'm not too familiar with the structure of rails apps but did you create a local copy or are you using the bootstrap files being hosted directly by github? You should be able to figure that out by checking one of your launched html pages and viewing the source, looking for something like
<link rel="stylesheet" href="http://twitter.github.com/bootstrap/1.3.0/bootstrap.min.css">
If it's a local page, there should be a directory somewhere in your rails app where the files are stored - perhaps there's a 'static' folder or something similar? Try file-searching for it, good chance you might find it.
(I use Django/Python for web projects but I'll look into Rails a bit and see if I find anything)

SCSS constants across stylesheets (Rails)

I'd have a long list of colors that I want included with every scss file in /app/assets/stylesheets. I tried including it in application.css.scss, but no luck.
What to do:
Create a colors.scss file with the colors you want accessible to layouts/application.html.erb.
Place colors.scss in app/assets/stylesheets/partials/shared. This is not required. I just like to be organized.
Within application.css.scss include the file #import "partials/shared/colors". You might prefer a different structure, but no need to append the file extension the asset pipeline knows.
(Optional) Remove the require_tree directive. Removing this directive and relying on #import enables your preprocessed stylesheets (e.g. *.css.scss) is a way to load styles in the order they appear.
What you just did:
The stylesheet_link_tag 'application' declared in application.html.erb is looking for application.css.scss by default. We've told the Asset Pipeline to use it in any view that uses the application.html.erb template. Now, each view will have access to the colors you specify.
More resources:
There are several deeper dives into the AP. I recommend you check them out. Here are some I found helpful.
Rails Guides
Secrets of the Asset Pipeline

Use CSS in a plugin in Ruby on Rails

I recently installed the fluid960gs plugin for rails, which includes some stylesheets. How can I use these stylesheets, located in the vendor/plugins/fluid960gs directory? is there a way to do it automatically using the stylesheet_link_tag function, or do i need to manually move them to the public/stylesheets directory?
You can reference them in the vendor directory, but it would be better if you just copy them over to public/stylesheets. This way, if you make any changes to them, you'll have the originals to fall back on, in case you need to.
I think you should check if you require the plugin in your compass.rb
Then you should be able to import the lib using #import method:
Add the following to your compass.rb config file:
# Require any additional compass plugins here.
require '960fluid'
Then make sure you have imported the grid library into your core .sass or .scss file with:
#import "fluid960";

Resources