How do I include custom SASS functions during precompile? - ruby-on-rails

I've successfully extended some SASS functions with Ruby code (http://sass-lang.com/docs/yardoc/Sass/Script/Functions.html#adding_custom_functions), and my extensions are loading correctly in development, but when I precompile my assets, the extensions are not loaded. The code lives in /app/models, but this is probably not the best place for it.
I've tried explicitly requiring the file in a few different config files, but it continues to fail to load during precompile. This also seems like a poor approach.
I know that the code is failing to load because the precompiled CSS leaves the function names in the CSS in plaintext. No errors are thrown.
So: Where's the best place for a file like this to live, and how do I get SASS to load the file during precompile?

The problem ended up being that I was requiring the file incorrectly, was using the config root rather than the app root. Assumed an error would be thrown when trying to include a nonexistent file, but evidently not. Once, I required the file correctly in config/application.rb, the precompile was able to access my SASS extensions
require "#{Rails.root}/lib/assets/colorable.rb"

Related

Force recompilation of certain files in rails assets pipeline

I'm using ruby on rails 4.1.9.
Is there a way to define a whitelist of files that should be recompiled anytime, even if they don't change?
For example: I have a few .js.erb files injected with some Rails variables. So, even if the original file is not changing, they need recompilation.

When are compiled assets being cached in rails

When I precompile my assets for a rails 3.1 app with rake assets:precompile it spits out an old cached version if nothing changes in the asset files. I can tell because my erb is making use of a constant that I was trying to change elsewhere in my app. One work around is to alter one of the css files (eg by adding a space etc) before re-precompiling but this is a pain and I would like to try and disable this caching if it is possible. Any ideas???
This is the expected behavior of the pipeline - the ERB is evaluated only once when you precompile. The value at compile time is the value you get in the file.
The caching is based on the checking the timestamp of the files. You could run Sprockets in production without precompiling (this is called live compiling), but you cannot turn off the caching because the performance would be dreadful - every single request would require Sprockets to recompile all the files.
Sorry :-(

Rails 3.1 asset pipeline - missing files from public/assets - why isn't this the default?

After I deployed my upgraded Rails 2.3.x -> 3.1 (rc4) app to our test environment this afternoon, all of our stylesheets and JavaScript files were returning 404 errors. We had added the rake assets:precompile task to our post-deploy script and it took a while to determine why the assets folder didn't have the pre-compiled files we expected.
In the end, the files weren't being compiled because apparently only application.css and application.js (+ non JS/CSS files) are processed by default.
We needed to change the following configuration value as follows:
config.assets.precompile += %w( *.js *.css )
Question: why isn't this the default?
I would have expected that anything that wasn't necessary to process as a manifest file would just get copied into public/assets. Much of what I've read on the asset pipeline is essentially "stick your assets in app/assets, configure the manifest files, and it should just work". Since the assets:precompile task didn't spit out any information about what it was doing, it took a while to determine that it just wasn't looking at the files we thought it would.
Is there any reason why this would not be a good value for the precompile configuration?
Thanks!
The idea is to have all your JavaScript and CSS always loaded in one shot, rather than loading bits and pieces as you move along. That way you always have the 'world' loaded and ready to work with, rather than having to include a whole bunch of individual files here and there.
It's a bit of a larger 'up front' load, but then the browser should keep loading all the javascript from cache. So the perceived speed of the site should speed up due to having everything cached and ready to go after the first request.
This was a controversial decision to include for Rails, but so is including CoffeeScript by default. Rails has always been an opinionated framework that way.
the new sprockets-based pipeline compiles all the files in /asssets/stylesheets and /assets/javascripts get compiled into application.css and application.js, respectively, by default.
In your views, you only need to link the application files, sprockets handles the rest.
Update:
Well, you don't have to make it all into just one file... You could have an shared.js, secure.js and public.js and have them each include the parts they need...
Think of them not as javascript files, but manifest files that establish groups of javascript files which you can then include as a group with a single javascript_include_tag. While the default is to include everything in the folder into a single file, you can be always pick and choose what to include, and what not.
The 'precompile' task simply runs those manifest files and compiles the multiple files into one, while pre-processing and sass or coffee script it runs across.

Sass - can it be compiled at runtime?

I've seen that certain Rails CMSes (like Radiant) have plugins that essentially compile Sass when a page is accessed. Is there a way to do this in a regular rails app? Is doing so performant? Basically, I'm looking at a way to remove the extra step of running Compass to compile my stylesheets.
I've not used compass specifically but there looks like there's a production flag so files are compiled - I couldn't imagine they'd build it to recompile per request in production, Radiant compiles it's css on Application startup and if you then commit those generated CSS files it doesn't try to generate them again AFAIK.
http://compass-style.org/docs/tutorials/production-css/
Sass and Compass automatically integrate with Rails. If you're using Rails 3, all you have to do is add gem "haml" to your Gemfile and all .sass and .scss files in public/stylesheets/sass will get compiled to .css files in public/stylesheets.
Compile per request? I think it could be a hit for performance. You should definitely use a caching strategy in that case. So that it compiles the stylesheet only if it is not in the cache.
You could create a helper method setup_stylesheet that will take care of setting up the css stylesheet. You call this method on the application layout.
setup_stylesheet will check if the css stylesheet is on the cache, and if it is there then use it. If it is not, then compile it.
Another approach:
You could set up an initialiser that will call Compass to compile your SASS stylesheets when the App is launched.
Is doing so performant?
There will be a massive performance hit when compiling at run-time.
As Nex3 (author of Sass gem) pointed out on another forum, there's no need any need to run compass watch.
I strongly advise putting the following into production.rb: Sass::Plugin.options[:never_update] = true - this is especially important if you're on Heroku. (you could also do this in your rack file, where you can also specify other options
Hmm, good luck

What is the best method for storing SASS generated CSS in your application and source control?

If you are using HAML and SASS in your Rails application, then any templates you define in public/stylesheet/*.sass will be compiled into *.css stylesheets. From your code, you use stylesheet_link_tag to pull in the asset by name without having to worry about the extension.
Many people dislike storing generated code or compiled code in version control, and it also stands to reason that the public/ directory shouldn't contain elements that you don't send to the browser.
What is the best pattern to follow when laying out SASS resources in your Rails project?
The compass framework recommends putting your sass stylesheets under app/stylesheets and your compiled css in public/stylesheets/compiled.
You can configure this by adding the following code to your environment.rb:
Sass::Plugin.options[:template_location] = {
"#{RAILS_ROOT}/app/stylesheets" => "#{RAILS_ROOT}/public/stylesheets/compiled"
}
If you use the compass framework, it sets up this configuration for you when you install it.
I always version all stylesheets in "public/stylesheets/sass/*.sass" and set up an exclude filter for compiled ones:
/public/stylesheets/*.css
Honestly, I like having my compiled SASS stylesheets in version control. They're small, only change when your .sass files change, and having them deploy with the rest of your app means the SASS compiler doesn't ever need to fire in production.
The other advantage (albeit a small one) is that if you're not using page caching, your rails process doesn't need to have write access to your public_html directory. So there's one fewer way an exploit of your server can be evil.
Somewhat related, but it's a good idea to regenerate your CSS during your capistrano deployments. This callback hook does just that:
after "deploy:update_code" do
rails_env = fetch(:rails_env, "production")
run "#{release_path}/script/runner -e #{rails_env} 'Sass::Plugin.update_stylesheets'"
end
Update: This should no longer be necessary with modern versions of Haml/Sass.
If I can manage it, I like to store all of my styles in SASS templates when I choose HAML/SASS for a project, and I'll remove application.css and scaffold.css. Then I will put SASS in public/stylesheets/sass, and add /public/stylesheets/*.css to .gitignore.
If I have to work with a combination of SASS and CSS based assets, it's a little more complicated. The simplest way of handling this is to have an output subdirectory for generated CSS within the stylesheets directory, then exclude that subdirectory in .gitignore. Then, in your views you have to know which styling type you're using (SASS or CSS) by virtue of having to select the public/stylesheets/foo stylesheet or the public/stylesheets/sass-out/foo stylesheet.
If you have to go the second route, build a helper to abstract away the sass-out subdirectory.

Resources