Why can't I add a plain link tag in Rails4 App - ruby-on-rails

Why is it so forbidden to add line like <link href="/assets/stylesheets/bootstrap/bootstrap.css" rel="stylesheet"> in my application.html.erb file. How else do I insert it?

It's not "forbidden" outright - it just skirts a lot of important Rails conventions which will likely create problems & inconsistencies down the line
There are several elements to what you're asking. Here they are:
Layout
Firstly, you need to use the correct helpers in your layout:
#app/views/layout/application.html.erb
<%= stylesheet_link_tag "bootstrap/bootsrap" %>
The reason for this is the same as using helpers in other parts of your Rails application - as paths change between environments & certain "backend" functionalities of the system evolve, you can't rely on using vanilla HTML to call "Rails-centric" methods
A pro tip is that if there is any reference to a path, or an asset, you need to use the helpers which Rails provides
Asset Pipeline
Further to this, you need to appreciate how the "asset pipeline" works.
One of the big benefits of the Rails framework is that it gives you the ability to organize your assets in the most effective way - by keeping them in the /assets folder.
Whilst great for development, your problem will arise when you go into a production environment - Rails prefers to serve static assets in production, which means that the assets will be pre-compiled & access in the public folder:
In the production environment Sprockets uses the fingerprinting scheme
outlined above. By default Rails assumes assets have been precompiled
and will be served as static assets by your web server.
To make sure this works properly, you need to use the path helpers to load the files dynamically; hence allowing Rails to access the files wherever they are on the system
--
Manifest
I would strongly recommend you look into the "manifest" feature of the asset pipeline:
#app/assets/stylesheets/application.css
/*
*= require bootstrap/bootstrap
*/

Related

Angular + .nghaml template: Referencing Precompiled Image Assets

I'm using .nghaml for my templates and using the following gems for Angular integration:
gem 'angularjs-rails'
gem 'angular-rails-templates'
My Rail view layouts are name.html.haml and using image_tag within them works fine. On production I can see the images.
In contrast, in my Angular templates (assets/template) with their .nghaml extension I can not use Rails helper image_tag and a direct reference does not work
%image(src="assets/sample_image.png")
The direct reference works locally, but on production images don't render.
This person (Rails Image assets in Angular Directive and template) had a similar issue, but using
%img(ng-src='assets/sample_image.png')
worked locally but not in production. And attempting to use image-url results in the error of undefined method (just as image_tag) because none of the Rails helpers seem to be working in the .nghaml extension.
The images that are working (Rails views with image_tag helpers) are referencing the precompiled assets which have their names changed with the addition of a md5-hash (based on the first linked article), but I'm having issues figuring out how to tell the nghaml templates what the new precompiled assets are called without a Rails helper method.
I ran into this issue with helpers a few months ago (Rails App to Angular: HAML + Rails Helpers) and didn't find a solution, but only recently needed to get images into nghaml templates rather than just creating what I needed with CSS.
I'm currently planning to just move the angular templates back to erb if I can't get this figured out, but if there are alternatives (or solutions) I'm unaware of, I'd love to hear them.
The solution proposed in the post Rails App to Angular: HAML + Rails Helpers will allow you to use the helpers (including the image_tag helper) in your haml files when generating the client-side html files.
One issue: According to the official repo for the angular-rails-template library, the .nghaml extension is no longer supported. You have to rename it to .haml
The bigger issue is that you're using Rails to serve a single-page JS app. There's no need for this, you can serve the site using nginx or Apache and control the caching and do cache busting there (nginx & apache cache busting tutorial)
If you're using Rails for the REST API, it should be de-coupled from your frontend AngularJS app.
If you're trying to do some fancy stuff in the templates aside from the cache busting, you should be doing it in JS and plain HTML. It's weird and strange but AngularJS and other frontend MVC/MVVM frameworks are different beasts compared to Rails and Django and the server-side MVC frameworks.

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

Using ExtJS along with the Rails Assets Pipeline

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.

How to "auto-build" and load different CSS stylesheet files when running a 'development' and 'production' mode?

I am using Ruby on Rails 3.0.10 and I would like to auto-build and load different CSS stylesheet files depending on if I am running my application in the development or in the production mode.
I would like to auto-"minimize" CSS files for performance reasons and to load those related "minimized" files because I do not want to show to the "public audience" the content of my comments present in my CSS file (note: users can access theme, for example, by using the FireBug plugin for the Mozilla Firefox browser). I would like to do that also for javascript files.
How can I do that?
P.S.: I am planning to switch to the Ruby on Rails v3.1...
In your layout you probably have something like:
<%= stylesheet_link_tag "production.css" %>
Just add another stylesheet there but wrap it in a conditional that checks the rails environment.
<%= stylesheet_link_tag "development.css" if Rails.env.production? %>
For Rails 3.0 there are many plugins to minify your css and javascript.
I use smurf.
gem "smurf"
Part of the process of minification is that it removes comments.
In Rails 3.1 production will uglify your javascript, so comments should be removed by default.
But if you insist on using a different stylesheet, take a look at the other answer.

Ways to organise CSS in Rails project

I would like to know what are the best ways to organise CSS code in Rails project?
I'm interested in how you do it and why.
If you would like to break up your css into multiple files during development you can add cache => true to stylesheet_link_tag and rails will automatically concatenate them into a single file in production. This also works for javascript_include_tag.
http://guides.rubyonrails.org/layouts_and_rendering.html#linking-to-javascript-files-with-javascript_include_tag
Generally, you should not have the client download a massive amount of CSS snippets, but pack them into a single file on the server to avoid rendering latencies. So you have the tradeoff of having functionality divided up into multiple files put wanting to send only one file to the client.
You could use SASS to have each piece of code inside a single include file and just include all of them together. This gives you the added advantage of mixins (kind of like macros) and variables among other awesome things.
Another possibility would be to use plain CSS and use something like Jammit to pack the stuff up to send to the client.
Regarding actual setups, I tend to have one file resetting the styles to a known default, a file for the basic layout (columns, default spaces, ...), and one file each for each area of concern for your specific design (headers, buttons, ...)
James and Holger's answers are very good.
Besides organizing CSS in my projects, I also had to change colour schemes a couple of times..
Trying to do consistent changes throughout many CSS files can be pretty painful (results may vary).
I ended up extending the Rails start-up procedure a little, to include a custom module "site_settings.rb"
through which I can define variable for colors and other CSS attributes, which I can then use throughout my CSS input files.
Whenever Rails starts up, and one of the input files has changed, it auto-generates the CSS files.
http://unixgods.org/~tilo/Ruby/Using_Variables_in_CSS_Files_with_Ruby_on_Rails.html
Since Rails 3.1 is out and sprockets replaced Jammit, here an excerpt form the Rails guides concerning the asset organization:
Asset Organization
Assets can be placed inside an application in one of three locations: app/assets, lib/assets or vendor/assets.
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.

Resources