Clear sprockets cache before rspec test runs - ruby-on-rails

In my Rails app, I'm dynamically modifying an app/assets/stylesheets/main.scss.erb file for some RSpec tests. If I run the RSpec tests individually, they all pass fine. If I run them together, every test fails except the first one. I suspect sprockets is caching the initial change, which lets the first test pass, but never updates the cache for the subsequent tests.
Is there a way to clear the sprockets cache (I'm using sprockets 3.7.2) before each test executes and force it to reload from the current state of the files?
Update 12/12/2018: Here's a little more context about what I'm doing. I have a Rails engine that powers several applications in my company. The engine loads a stylesheet inside the engine and it also looks inside the host Rails application and loads a second stylesheet (i.e. we don't require the Rails apps to add the stylesheet to the application.css manifest file themselves; the engine handles it). We recently found a bug that prevented the engine from loading the application level stylesheet, so I fixed it and started adding some tests in the engine. My first attempt at testing was to create a page that had some special divs. The divs use CSS IDs that are defined in the various stylesheets. If the divs end up with the expected styles, I know they only got those styles from the stylesheets (which confirms that they got loaded). This strategy works, but it requires code spread out in the engine and dummy application (inside the engine). I then started experimenting with having the tests dynamically append CSS rules into the stylesheets when each test is executed. This strategy is a big improvement because it keeps all the interesting code in the test. Anyone reading a specific test can immediately see the styles that are being added, and the files that are being modified. Everything is contained in the test. Unfortunately, even though I'm resetting all the necessary files between tests, it looks like the assets cache isn't getting invalidated.

Related

Rails 6 - Should I put my CSS & JS in rails asset pipeline or webpacker or through Amazon Cloudfront? Which is the most efficient?

I use to host my CSS files in the rails asset pipeline and JS on webpacker. I recently realize my webpage has been loading slower and slower.
I ran Chrome lighthouse on my site and found that my CSS and JS assets are "render-blocking resources" and causing my page to load slower.
I've already tried moving all of my CSS and JS over to webpacker (semantic-ui css is still being imported by the rails asset pipeline, had lots of problems trying to make this work but couldnt still)
I notice on Chrome lighthouse that my load time improved marginally, I guess its from the minification of CSS and JS by webpacker but it's no where near the improvements I was looking for.
So my question here is, what is the most efficient method to serve CSS and JS files for rails app?
My app is hosted on Heroku's Hobby Tier.. could this be a factor as well?
Both approaches should allow you to achieve similar results. I don't know rails asset pipeline, but if it's used similarly to webpack it just changes your files on the build time & it's up to you how much code the user gets to download.
First of all, you can check the output size - in webpack, you can check the build standard output, or directly check the files it creates.
One trap you could be failing into with webpack is to have it set up wrongly. It could anything, from not minimizing code when for production build to having loades set up in a way that makes your images included directly inside js as data URL.
One advantage of using webpack, is that allows you to set up more complicated loading logic - for example lazy loading. Here something more about lazy load:
https://dev.to/marcinwosinek/lazy-load-library-in-application-build-with-webpack-5757

Sprockets cache not invalidated by file change

I'm running a test Ruby-on-Rails app using Webrick in a test environment. The automated end-to-end test accesses an admin page which causes a JavaScript file to be updated which is used by another admin page. The problem is that the second admin page does not see the update, but instead gets the old copy of the JavaScript file. I can see the changed file on the file system, but even if use curl from the command line, I still get the old version of the file. The test used to work (at least with Rails 4.0, if not 4.1). It is just now that I am trying to update to Rails 4.2 that this problem has arisen.
Is there something I can do to to tell Rails/Sprockets to forget its old cached copy of the JavaScript that was updated? I know when I am updating it, and wouldn't mind even resetting Sprocket's entire cache if I couldn't do it selectively. What I can't do is restart the server each time a JavaScript file gets updated.
I tried many approaches to making Sprockets "forget" its cached copy, but it seemed very determined to remember, and I began to have the sense that I was fighting against a firmly entrenched design decision. In the end I decided that, just for my generated-on-the-fly JavaScript files, I would avoid sprockets altogether, which meant handling the compiling and fingerprinting of the files myself, and writing my own version of javascript_include_tag just for those generated files.
For reference, the compiling and fingerprinting is actually fairly easy:
require "uglifier"
require "digest"
minified_content = Uglifier.compile(File.read(my_generated_js_file))
fingerprint = Digest::MD5.hexdigest(minified_content)
fingerprinted_file = File.basename(basename, '.js') + '-' + fingerprint + '.js'
(and then just write out the fingerprinted file to public/assets).

Precompile Grails CoffeeScript assets for Testing with Geb

I would like to create reliable functional tests for Grails application with Geb which wouldn't take ages to run so me and and other team members can run them before each commit. I'm using Grails Asset Pipeline with CoffeeScript files split into many files and grouped using index files.
The problem is following:
In development and test environment the CoffeeScript files are compiled for the first URL hit - for the first time the page is loaded. As the application grows this takes more than one minute (especially on CI server) so each of my Geb specification needs to start with waitFor(120){...} to ensure the specification will wait until the CoffeeScript get compiled.
I could run the functional tests with -war flag but than all the CoffeeScript files present get compiled multiple times (once for every reference from the CoffeeScript file, i.e. one big bundle or the application coffee, once for index file once for the file itself). Currently the compile process fires for nearly three hundreds of files instead of two. If I try to exclude some files using the grails.assets.excludes than the files are missing from the application bundle completely.
Are there any suggestion how can compile just the files which are needed but not excluding them from bundling into other files?
The structure can be seen in our test app and core plugin.

On demand asset compile Rails

I've some html5/ js game widgets that are shared between my webapp and my ipad app. I've used some ERB code here. The process is, whenever the user purchases a game from ipad, I copy all these assets to a temp folder, zip it and send it back.
Now the problem is, since I'm using ERB, the code is not compiled. This game widget folder is not a part of the asset pipeline as it is required only in certain cases.
Is there a way I can compile these games on demand before copying?
From what I can understand, I'd say your problem lies with your use of ERB code
ERB, like HTML, can only be rendered by a specific technology stack (in our case Rails). This means you need all the other dependencies to make it work, which is where you're hitting problems
Rails
I would recommend your best bet is to create a Rails process to "compile" the JS for you
As a matter of speculation, I'd recommend you'll have to look at creating either a queued job or a scheduled rake task to do this:
Create a special controller action
Use the controller action to load required data
Use a way to create a ZIP file
Save the file
If you'd like me to write some code (although I've never done it for this before), I'll have a look at it for you

What exactly "config.assets.debug" setting does?

I have started development of simple rails application. After several hours work I have notices that somehow the deleted css is still applied to the web pages.
In order to fix the issue I executed the following actions several times:
stop/start server
use rails server
use torquebox server
delete browser cache
but nothing changes. It was very strange - the new css definitions were applied, but those that I have deleted were still there. So, I gave up and decided to create new project.
I have setup the new project (its scaffold is the same as the first one) and when I open one of the views, the styles from the old project were applied too. I have decided to look again into http://guides.rubyonrails.org/asset_pipeline.html and find out that setting
#Expands the lines which load the assets
config.assets.debug = false
solves the issue. But what is this option doing exactly? Why the old projects css were applied when this was true?
This option's effect is well described in this post, but I'll summarize it here as well. The value of changing config.assets.debug lies in a compromise between page load time in development and ease of debugging.
Basically:
config.assets.debug = true: assets are served individually, organized just as you see them in development. Preprocessed languages like SASS or CoffeeScript will still show up as their target languages (i.e., CSS and JS, respectively).
config.assets.debug = false: assets are bundled into files like application.css and application.js. Error stack traces will likely not have the correct line number any more and it is harder to map those back to your original code.
If you get to this web page, there is a possibility you are here because you are using the Rails Asset Pipeline and you made changes to one of the javascript files and reloaded the page and the change is not reflected when you search in the Sources tab in Chrome.
As stated above, config.assets.debug = false prompts the Sprockets gem to bundle all the individual javascript and css files into one application.js and application.css respectively. Also Sprockets runs the the SASS and CoffeeScript (if you did not use --skip-coffee) preprocessors on all associated files to generate css and javascript files that the browser can understand.
One important note is the following. Ruby Guides says this about debug = false:
Assets are cached on the first request after the server is started. If
any of the files in the manifest have changed between requests, the
server responds with a new compiled file.
This means if you do not change the css or javascript files between requests, then a cache will be used. As soon as you change a file, the cache is invalidated and a new cache is created for subsequent requests.
Consequently, if you made changes to a javascript file and the change is not reflected on page reload, it has nothing to do with this option config.assets.debug.
There is this other option called
config.action_controller.perform_caching.
But by default this option defaults to false in development. That is, by default, caching is only enabled in your production environment. And in current versions, Rails only ships with Fragment Caching by default. You have to install separate gems for Page and Action caching.
Fragment Caching allows a fragment of view logic to be wrapped in a cache block and served out of the cache store when the next request comes in. But then again, cache fragments will also be expired when the view fragment changes (e.g., the HTML in the view changes).
So the question remains why is the change of your javascript not reflected? The answer is Google Chrome, the browser itself, is caching the page despite your Rails settings. To remove the cache, close the current tab, open a new tab, and visit the site again.

Resources