Force recompilation of certain files in rails assets pipeline - ruby-on-rails

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.

Related

Force reload of static assets with embedded ruby in Rails

I have a js.erb file that uses an environment variable to set a string that will occasionally change. I would like to be able to change the environment variable and immediately be able to load an updated javascript file, but since the source erb file doesn't change, Rails doesn't know it needs to be compiled again. Is there any way I can force it to recompile?
Note: this is in a dev/test environment, not a production environment with precompiled assets.
Note #2: this feature has actually been addressed by sprockets, however the most recent release is older than the PR that adds the feature. I'm looking for a temporary solution that accomplishes the same thing (see https://github.com/rails/sprockets/pull/365)
I was able to accomplish my goal with the answer from this question How to add a rails asset dependency to an environment variable with sprockets?
However, first I had to upgrade sprockets to >= 3.0.0.

Is it possible in Rails to have different assets directories for different environments?

Before executing Asset Precompile (rake assets:precompile) I want to apply gulp tasks to my JavaScript files which are located here:
app/assets/javascripts/my_angular/directives/*.js
app/assets/javascripts/my_angular/controllers/*.js
So when I later run rake assets:precompile it will pick already processed-by-gulp files.
But the problem for me is that I do not want to simply overwrite existing JS files with its gulp output files since I still need original, not touched files for comfortable development.
I think I need to have two folders:
1) development_assets
2) production_assets (auto-generated folder with gulp output)
Is it possible in Rails to have different assets directories for different environments? (development, production). If yes - how to configure it?
Maybe there is another solution for my problem? Without having two separate directories... I am open to suggestions.
You can configure the assets path with config.assets.prefix = '/gulped-assets'. If you do that in config/environments/production.rb, it'll apply to production but not development, letting you still use your original files in dev. You'll need to either make sure your deploy process runs Gulp before asset compilation, or run Gulp locally and include /gulped-assets in your repository.
You can also add a preprocessor to the asset pipeline, which would leave you needing just one /assets directory. You do that by specifying a file extension and a handler, then adding the extension to all the files you want processed that way, just like you have with .sass, .erb, etc. To crib from the Rails examples, it looks like this:
module BangBang
class Template < ::Tilt::Template
def prepare
# Do any initialization here
end
# Adds a "!" to original template.
def evaluate(scope, locals, &block)
"#{data}!"
end
end
end
# config/initializers/bang.rb
Sprockets.register_engine '.bang', BangBang::Template
Then any file containing .bang in the extensions will have a ! appended to it. There's already support for a lot of different tasks out there, so perhaps you can avoid Gulp in favor of a Sprockets-only pipeline. Depending on your Gulp tasks, you might even be able to shell out and run data through them to build a hybrid pipeline.
Or, you can go the other direction and replace Sprockets with a Gulp-only pipeline. There are a lot of people doing that, and anything I'd write here would be long and only duplicate their work, so check out the gulp-rails-pipeline gem and perhaps read Gulp - a modern approach to asset pipeline for Rails developers for another angle on it.

How do I include custom SASS functions during precompile?

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"

Asset Pipeline :: Specific Resource compilation

How can I run specific compilation tasks with rails/asset pipeline/sprockets within my application?
Basically, I have sets of user created css for an application; users upload css for their parts of the application (security considerations aside etc, already handled). How do I run a task to compile specific css sets into the main css I have? This is not a live compilation issue, I just want to take an input, compile that to a file, and serve that that on demand, which is more a 'I need this set of css precompiled at will when I want to precompile it within a running application'
I'm updating something implemented previously where I was able to haphazardly serve user generated css, I'd like to integrate this with the asset pipeline. How can I get greater control over the asset pipeline? I'm assuming I need to learn more about Sprockets, but I'd be curious what anyone could add to assist.
Per user CSS files would be possible, but to use Sprockets and the pipeline in the intended way to generate the files is going to take a bit of messing about.
To generate a user CSS file you are going to have to:
1. Generate a manifest for the user.
The manifest would include the main css via a sprockets directive, and require self at the end along with the user css.
The manifest file would need a name that is unique to the user
2. Compile the manifest.
You won't want to compile them all, so you'll need to write something to do just the one you want.
3. Add the new manifest to the pipeline manifest
This is a YAML file that holds the mappings between the name of manifests and files in the pipeline and their hashed counter-parts. You'll need to add your new (or updated) file hash to this without clobbering the other entries.
4. Restart your app.
This is required because Rails read in the pipeline manifest when it starts up, so you would not see any changes you'd made until this occurs.
==
Then you will be able to reference the username based CSS file for the user.
The with this approach is that each time you deploy the custom manifest would be overwritten.
If you are storing the user's custom CSS in the database you could write out the custom user manifests at each deploy.
Another approach is to use the pipeline for the main CSS and ignore it completely for the user CSS, just doing what you do now. Use on link for the pipeline CSS and a second for the user CSS. You could still minify the CSS when the file is created, but if the extra request is out of the question then something based on the above.
Best of luck!

Are there any configuration options for RoR asset packager?

Regarding the Asset packager plugin for RoR.
Is there a way to configure it, so that it packages JS/CSS files in development environment, but without minifying the JS files?
Doesn't seem like it, but it's easy to add:
Add "development" env at this line or setup another ENV variable and if it exists it can be included automatically so you don't mess around with code more than once.
For the compressed_file method (which compresses the js and css) you could add an option (or have it read from the ENV) and compress or not depending on it
No.
def javascript_include_merged(*sources)
It only expects sources and does not have an options hash like most methods that accept options do.

Resources