Using ExtJS along with the Rails Assets Pipeline - ruby-on-rails

For an application built on top of Rails (3.1.8) with ExtJS 4.1, we have the following files layout:
app/
assets/
javascript/
application.coffee
WID/
Lots of coffeescript files and folders.
public/
extjs/
ext-all-debug-w-comments.js and the whole ExtJS framework.
Our application heavily relies on the Ext loader (Ext.Require) to dynamically load files based on users rights / allowed modules. We would like to keep this functionality as much as possible, so only the required files are requested from the server. Bandwidth isn't really an issue, as the application is intranet-based (On a LAN).
In development environment, everything runs smooth. In production environment however, we are having problems. It looks like either the "rake assets:precompile" task is concatenating all files into an application.js file, and then when accessing our application the Ext loader complains that it can't find individual files (Because assets/WID/.../file.js isn't being served by the rails server).
So right now, i'm not sure what would be the best move to take... Is there anyone able to help us with a successful Rails + ExtJS production setup taking the best from the assets pipeline?
Thank you,
Pierre.

I think you should move your javascripts (and generally all the assets) from your public into vendor/assets/javascripts when you are in development environment. This way the asset-pipeline gets in charge.
EDIT: You may consider reverting your manifest file to application.js, not application.coffee. Generally it is a bad idea to rename these special files : application.css and application.js .In case you have some coffescript to add , just create a new file and place it in an asset directory.

Related

Rails 4 Asset Pipeline: Asset missing fingerprint in asset_path from js

I am deploying a Rails 4.0 application which includes HTML partial templates as assets for our front-end javascript framework. Although these templates are part of the asset pipeline and are properly precompiled, when I call asset_path from embedded ruby in our js files, it returns the path to our templates without the fingerprint.
I am quite certain that this is purely a Asset Pipeline question, but to give you a complete sense of our tech stack: We use Rails 4.0, Ruby 2.1, AngularJS for our front-end MVC framework, and AssetSync to synchronize our assets between Rails and our CDN.
An example of where this occurs (in a file included in app/assets/application.js.erb:
$routeProvider
.when('/', {
templateUrl: "<%= asset_path 'home.html' %>",
controller: "HomeController"
});
This works great locally, but as soon as config.assets.digest = true in production, the call to asset_path does not properly factor in the fingerprint. The templates are in the app/assets directory within a new subdirectory templates. So in the above example, the home.html asset is at app/assets/templates/home.html. Our javascript has itself been precompiled at that point, so I'm thinking that it might be an issue of which order the assets are precompiled in.
I've noticed a few issues on the Rails Github (1, 2, 3) and a couple of SO posts about fingerprints not being set properly (1, 2), but can't find anything about them not being included at all...
Any help or ideas that you can provide would be much appreciated.
Edit 4/15: forgot to include that the extensions on my application javascript file DOES include .erb (app/assets/application.js.erb). Thanks Alex for catching that. I've updated it above.
Also, following instructions in this article on Heroku, I confirmed that running puts helper.asset_path("home.html") from within a Rails console running in production prints a properly fingerprinted URL for that asset.
This appears to be an issue with the AssetSync gem. I removed it, reconfigured the app so that Rails serves the assets, and the fingerprinting works fine.
If anyone else finds this question and is running into the same issue, I would recommend against using AssetSync. According to Heroku:
Many developers make use of Amazon’s S3 service for serving static assets that
have been uploaded previously, either manually or by some form of build process.
Whilst this works, this is not recommended as S3 was designed as a file storage
service and not for optimal delivery of files under load. Therefore, serving
static assets from S3 is not recommended.
Amazon CloudFront is the preferred method of serving assets through a CDN, and is very easy to configure with a Rails app that serves its own static assets, accomplishing the same goals as AssetSync.
I'm pretty new to this stuff, but to get the asset_path to work, don't you need a .erb on the end of that file?
Check out the bottom of this article for more info:
https://devcenter.heroku.com/articles/rails-4-asset-pipeline
If it works in development, that may not help. There is a helpful section on debugging at the bottom of the article though.
Update
Here's another article that could help:
https://medium.com/self-directed-learning/9ba1f595102a
Flipping on this configuration in Heroku made some of my asset pipeline problems go away:
heroku labs:enable user-env-compile -a yourapp
Hope this helps!
Alex

In Ruby on Rails, what is an "asset"?

What's considered an "asset" in the Ruby on Rails universe?
Are user generated files, such as images uploaded by the user, considered assets? Where should they be stored in the standard file structure of a Rails project? Should they be kept clear of any asset related directories like:
app/assets
lib/assets
public/assets
Relevant: The Asset Pipeline
Generally asset is anything that browser loads after it gets the HTML page. Meaning javascript, css and any images. But as you pointed out there are two different image types in a rails project.
1) the images related to your css and layout design, those go under the app/assets/images
2) the images that your users upload, those normally go into the public/system or public/uploads folder depending on what you use to receive the uploads
The lib/assets (or sometimes vendor/assets) is where you supposed to place js/css/images related to your front-end design and provided by third party libs. Say if you want to pull in some css or a js framework, that were you should place it.
And finally public/assets is where rails will compile your layout assets from the app/assets and vendor/assets folders when you run rake assets:precompile task for production.
To have it short, your design stuff goes to app/assets, and the user uploads go into public/system
User-uploaded files are not part of assets, and should definitely be kept clear of asset-related folders. You should put them somewhere in your public directory. I put mine in public/uploads, which is a common convention. And then you should ignore those files in git (or whatever VCS you're using).
Assets are basically: javascript, stylesheets, fonts, and images which are part of the site design itself, not part of the user-uploaded content.

Understanding the Rails 3 Directory Structure

I've found several sites online that explain the DIR structure of a Rails app, but I'm still not clear on a few, mainly:
/vendor
/lib
/public
What should go where? I want to know the best practice. For example, I have jQuery plugins, should those be located in /vendor? /public? /lib? I've read all 3 from different sites online.
Thanks
Vendor is third party code / libraries, so, yes, a good place for jQuery plugins.
Public is for static assets, stuff that gets no benefit from being in the asset pipeline.
Lib is generally used to contain your code that is not specific to the app. i.e. stuff you use in multiple apps. There is a trend to put domain logic in lib e.g. domain classes not based on ActiveModel. Gary Bernhardt (https://www.destroyallsoftware.com/) is a proponent of this.
Typically the contents of /public are directly served by the web server (nginx, apache etc.) without intervention from rails, so traditionally all of your static assets (images, stylesheets, javascripts etc.) went in here. You can still put your javascript in there but it's a bit old fashioned.
Rails 3.1 introduced the asset pipeline which changed all of this. Assets in app/assets, lib/assets and vendor/assets all get servers up by the asset pipeline. Normally your application specific assets would go in app/assets and 3rd party libraries (such as a query plugin) would go in vendor/assets. If you were developing your own set of jquery plugins you might put them in lib/assets. Assets will 'work' no matter where you put them though - it's just a question of organisation.
Gems can also have their own asset folders, for example the jquery-rails gem bundles jquery and allows your app to serve up jquery without actually copying it into your app. I find this even neater than putting things in vendor/assets.

Rails 3.1 Assets are being fingerprinted in production but rendered HTML is not

Everything works great in Development. And app deploys as normal with Capistrano. Assets (javascript & css) appear to be fully pre-compiled and each, along with images, are given a "fingerprint". Problem is when using image_tag("image-name.png") in my view the html it creates in production doesn't include the 'fingerprint'.
The rendered HTML we get in production:
<img alt="Image-name" src="/assets/image-name.png" />
instead of, what I would expect, should be:
<img alt="Image-name" src="/assets/image-name-b89cae2830c2901f844c353b3f3942fe.png" />
So which of Rails 3.1's myriad config options did we botch?
Edit
The troublesome images appear to be those included in a 3rd-party Colorbox image viewing tool we use. Rails 3.1 is fingerprinting its assets (border.png, etc.) but, clearly, the source code for this javascript library doesn't use helpers like image_tag. So in production it is still looking for images named /assets/colorbox/border.png. Currently images are in /vendor/assets/images and work fine in Development. Is there a way to prevent just these images from being "fingerprinted"?
Well, here's how I hacked the 3rd-party files to make things work:
The offending images were in files like vendor/assets/stylesheets/colorbox.css. I first changed the extension of the files to .scss then I changed each url(colorbox/image.png) to image_url("color box/image.png") and now everything is peachy. Assets are served normally in development and fingerprinted in production.
Still like to see the "proper" way to add 3rd-party (vendor) javascript libraries & css to a Rails 3.1 app. Rails team must have anticipate a drop-in solution that doesn't require editing?!? So, please, feel free to offer up other solutions.
Aside: where I previously had manually configured my Capistrano recipe with:
run "cd #{release_path}; RAILS_ENV=production bundle exec rake assets:precompile"
…and its accompanying after deploy:update_code …. I have now removed those lines and instead added load 'deploy/assets to my Capfile. I don't think this makes any difference in the above problem but I wanted to document it anyway as adding your own recipe for pipeline precompiling is no longer necessary in Capistrano 2.8 as it was in the 3.1rc days.

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.

Resources