Understanding the Rails 3 Directory Structure - ruby-on-rails

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.

Related

Ruby on Rails asset organisation folders

I'm using ruby on rails 5. What is the difference app/assets, lib/assets and vendor/asset?
If I write my own js scripts should they be included in the app/assets? How about if I use a bootstrap library where should I put it at?
And regardless which folder they are in, i am able to access them using javascript_include_tag? Example:
javascript_include_tag "xmlhr"
As described in the asset pipeline guide:
app/assets is for assets that are owned by the application, such as custom images, JavaScript files or stylesheets.
lib/assets is for your own libraries' code that doesn't really fit into the scope of the application or those libraries which are shared across applications.
vendor/assets is for assets that are owned by outside entities, such as code for JavaScript plugins and CSS frameworks. Keep in mind that third party code with references to other files also processed by the asset Pipeline (images, stylesheets, etc.), will need to be rewritten to use helpers like asset_path.
Me, I only use app and vendor. My stuff goes to app, naturally. And 3rd party stuff (jquery plugins, bootstrap themes and whatnot) goes to vendor.
app/assets
It should include all the assets written by you and only relevant to your project.
lib/assets
It should include all the assets which are created by you but can be extracted to be used by another project.
vendor/assets
It should include all the assets downloaded/purchased from third party like Bootstrap.

Spree application and main rails application CSS loading

I have a Spree application and some pages that are not part of the spree application. My problem is that styles are shared between those pages. (they look similar, but they have their own asset locations)
How do I do it so I don't have to maintain two sets of stylesheets/JS files?
Just extract common stylesheets to separate CSS files then include them in your applications:
use build process (such as Asset Pipeline)
symlinks (not a best way but I think it will works too)
submodules (if you are using Git)
put common stylesheets to separate gem and use it as part of Asset Pipeline (like any Rails gems with assets inside)

Rails: What's the advantage/disadvantage of putting scripts and stylesheets directly in public folder?

So that I could take advantage of all the already well developed front-end tools like requirejs, bower and grunt... It's just that so many of them somehow get crippled going with rails.
Primary advantages:
It is easier to load third party scripts this way. It is always possible and sometimes easy to put these through the asset pipeline, but it is also often tedious and you lose bower.
Scripts in public will not be digested, so they can be loaded by non-rails pages easily. For example, you use a javascript file on your site, and also need to load it on another, e.g., PHP site, or need to allow other people to load your script for an embedded API, etc... then you'll need to serve from public.
Primary disadvantages:
Because you're not using the asset pipeline you lose:
Asset combining and compression. Asset pipeline CSS and Javascript will be loaded in a single HTTP request each, and the content can be minified. This makes first page load on your site faster, especially if you have lots of client code or a site that needs to be super snappy for occasional visitors.
Digesting. The asset pipeline protects you 100% from cache vagaries and potentially having different users seeing your site with different version of your assets. Once you deploy, every visitor will get the new assets.
Relatively automatic etagging. Once those visitors get the new assets, their clients will generally cache them for a long time. Rails can afford to let assets cache essentially forever because digesting ensures you're not punished for this later.
So there are pros and const both ways and neither is right or wrong.
It's just that so many of them somehow get crippled going with rails
Pipeline
The reason is you're not meant to use the likes of Grunt etc with Rails. Rails' asset pipeline is only meant to contain the files which can be precompiled & used directly in your application:
The asset pipeline provides a framework to concatenate and minify or
compress JavaScript and CSS assets. It also adds the ability to write
these assets in other languages and pre-processors such as
CoffeeScript, Sass and ERB.
This will typically mean compiled third party JS/CSS files, and your own application JS/CSS files. I don't see how something like Grunt would provide any benefit to this? All it does it create a way for you to manage dependencies, versioning & source of particular assets?
--
Public
Using the files in your public folder isn't such a big deal. One of the most prominent things it does do is to exclude those particular files from the file digest processs, allowing you to use the likes of endpoints (scripts) which can be accessed by other services (outside the scope of routes.rb)
A good example of this is when we created an analytics system, and put the analytics.js into the public folder, so all the widgets could access it. This allowed other sites to access this file, regardless of the state of the asset pre-compilation.
One caveat to this would be you could perhaps have some way to store a "pseudo" file in the public folder, with it routing dynamically (with ERB) to the precompiled equivalent, but I've got no experience with this
--
Pipeline
The benefits of keeping your assets inside the asset pipeline, as stated by gwcoffey, are:
They will be compiled as you design (I.E primarily into application.js, but also into any other files you define too)
You don't need to worry about versioning (every precompile is basically a way to better the version without worrying about grunt etc)
You can include as many dependencies as you want - meaning you're able to create a totally modular set of assets which can be used throughout your app; rather than single scripts which will have their own dependency base
Recommendation
Unless you maintain third-party scripts which need dependencies to run, I would not recommend using Grunt for Rails. If you develop your own JQuery / Javascript scripts, by all means run them through Grunt etc; but for use in your app, I'd steer clear
Hope that helps!

Best practice for including vender assets in Rails 4 Application

I can't find a good resource for explaining how to include a more complicated 3rd party package that includes js, css, and other types of assets within the same plugin. For example, the plupload plugin has a lot of different assets spread out in multiple folders. I have put it in the vendor/assets/plupload/ folder and then require the tree in my manifest file, but then it refers to other other files with a relative pathname that works in development, but the path changes in production. I can then change the references to use asset_path, but then I am modifying the vendor code which just seems wrong.
I know there is a gem out there for the plupload library, I am just using it as a case study to try and understand the best practice for including a more complicated 3rd party library than what the Rails Guides show.
Thanks!
You can place the contents related to any plugin or library in a single folder public folder. This will make all your assets available and there should not be any issue.

JS and CSS in Rails 4

In Rails 4, the JS or CSS files, should I putting them in vendor > assets or in app > assets?
There are 3 asset locations in Rails
/app/assets/{images,javascripts,stylesheets} for the application-specific assets.
/lib/assets/{images,javascripts,stylesheets} for library assets. It's not very clear the boundary between this folder and the others, there is a lot of overlap. However, you normally place here assets that are shared across multiple apps under your control or libraries that don't normally tie specifically to the application.
/vendor/assets/{images,javascripts,stylesheets} for vendored assets. You should place here assets downloaded from packages where you have no control and that are not intended to be manually edited. This is the case, for instance, of bootstrap, jquery or other frameworks, as well as javascript plugins.
There is one important difference to keep in mind. Assets in /app are reloaded on every request. The other folders are not autoreloaded, thus if you make changes you will need to restart the server.
Your CSS goes in app/assets. CSS from 3rd party vendors goes in vendor/assets.

Resources