Using only relevant assets with Rails 3.2 + Sprockets + LESS - asset-pipeline

I'm a bit new to Rails, so far so good. The assets pipeline/sprockets is pretty neat but I'm a bit confused. When generating scaffolding for my various controllers, individual css/SCSS files were put into app/assets/stylesheets. But for my project I'm using LESS not SCSS, so I replaced them with .css.less files.
The problem I'm running into is that if I add CSS to a controller (let's call it "home.css.less" for example), it gets included in every view, not just views belonging to the "home" controller. If I remove "*= require_tree ." from the application.css file, then the file's not included in any views.
How can I specify CSS code for a particular controller/view using the Rails assets pipeline?
application.css:
/*
*= require twitter/bootstrap
*= require_self
*= require "application_custom"
*/
home.css.less:
body {
background: asset-url("circles.png") no-repeat;
}
The above results in no background being applied, even to the home controller's views.

This is a fairly common request; many sites have home page specific CSS that they don't want applied over the whole site.
I will make a couple of comments about this before providing the solution, if I may.
The purpose of the pipeline to present one CSS (and one JS) file to clients. The digest is added to allow the addition of server headers that force remote clients to keep a copy of them in their local cache.
The single request and aggressive caching strategy are the default for Rails for performance reasons; each request slows down the page.
Unless the home page CSS is really extensive, I would recommend using the default behavior. If the desire to split this out comes from clashes in CSS selectors between home and other pages, I suggest changing the CSS structure to over come this.
There are at least two common solutions:
The first would be used if you want to manually a different file for each controller.
<%= stylesheet_link_tag "application", controller_name %>
For this to work in production you have to tell rails to precompile all the individual CSS files (in application.rb):
config.assets.precompile << '*.css'
The second is to add a helper to render CSS only when it is required from a view.
I recommend the top solution on this question. You will have to modify the helper names for CSS. That will render a tag for the required CSS only when it set in the view.

Related

How to compile css and jss in laravel mix

How to compile css and jss in multi page application in laravel page wise using laravel mix . suppose i have page 1 , page 2 and page1 have test10.js, test11.js, test12.js and test10.css, test11.css,test12.css and page2 have test21.js, test22.js, test23.js and test21.css, test22.css,test23.css and so on. So someone let me know how to compile the css and jss in multipages applications.
For most cases, it is a good practice to optimize a big chunk of your assets to work on almost all pages. It is not a big problem that some pieces are not getting used on every page because caching gives better performance results when you only use one file that stays the same on every page.
There is an option for compiling multiple assets. You can just call the js() or sass() or an other method an other time. This time referencing an other file that needs to be compiled. In your layout you can add them per page.
What I like to do is the following:
I add a #stack('js) to my main layout.
For every piece of Javascript that only needs to be included at a single page I use #push('js) and #endpush.
Sometimes, when the code gets to big to handle, I add a js() method in my webpack.mix.js file. This gives me more freedom in writing my javascript.
A stack has a big advantage: It accepts multiple entries. This comes in handy when you use partials to build up your view and you want to keep the Javascript logic in the same files.

Whats the proper way of including js/css with ajaxed html partials?

I'm building my first ajax-heavy application and am not sure of the proper approach for such things.
If, for example I ajax in a html partial (a form), with:
$('#content').load('form.html');
how should I include the javascript and css?
I can, of course include them in the original document, but that seems wasteful if the form is never loaded. I can inline them (in form.html) with <script> and <style> elements, but that seems like the wrong approach.
You can use a separate JS file and load it using $.getScript() in the .load callback.
Inline CSS should work fine, but since you run the risk of it messing up your main page, you should load it as part of the main page and not with AJAX.
If it were me, though, I wouldn't be afraid to leave a few extra lines of well-targeted JS and CSS code in your main page -- it's more efficient to load it with the other JS and CSS at the beginning, in the same file(s), than to fire off another network connection and wait for it to download.
The $.getScript() would make an additional http request to load the js file that is to be used in form.html.
So, say for example, if you load 20 forms via ajax, you have to make 20+20 http request( 20 for loading js file and 20 for loading the html for forms)
A possible optimized approach is:
loading the all the css ( minified) at the beginning.
IF a single js file is real large even after minifying,
Arrange the js functionality based on the PROABABILITY of use in different files ( (the fewer number of files , the better).
Minify those files and load the file with highest probability at the beginning .
And then use $.getScript() to load the file after checking if the file has already been loaded.

How to render partials from unrelated controllers in one view....almost Amazon style

How can we render many partials from different controllers into one view?
The local variables of each partial are calculated separately in different and independent controllers.
What I really have to make things more specific, is a home layout, and in that layout that has dynamic content, there's a partial that only handles site wide news announcements, and these are independently updated.
I know a quick hack such like:
render :partial => '/news', :locals=> {#news = News.last}
but I want something more "correct". Like I've been reading about :templates rendering but i'm not sure how it works exactly in Rails 3.1.
Any help would be highly appreciated!
2.2.3 Rendering an Action’s Template from Another Controller
What if you want to render a template from an entirely different controller from the one that contains the action code? You can also do that with render, which accepts the full path (relative to app/views) of the template to render. For example, if you’re running code in an AdminProductsController that lives in app/controllers/admin, you can render the results of an action to a template in app/views/products this way:
render 'products/show'
Rails knows that this view belongs to a different controller because of the embedded slash character in the string. If you want to be explicit, you can use the :template option (which was required on Rails 2.2 and earlier):
render :template => 'products/show'
Sources: http://guides.rubyonrails.org/layouts_and_rendering.html#using-content_for
Should have read in more details.

dynamic theme in MVC3

I have been working on a MVC3 new project where I wanted to introduce the concepts of dynamic themes.
Instead of creating a bunch of .css files and dynamically linking to the
right one, I wanted to use a <style> section in master <head> section
that specifies the values to use for the selectors and their properties.
The values would be pulled from a database and written to header section in style,
look like this:
<head>
<style type="text/css">
.testClass { color:Purple;background-color:LightGreen; }
</style>
</head>
Not an answer on how to achieve this end, per se, as much as a suggestion that you reconsider. I have seen this approach taken firsthand several times over the years, and it invariably ends up first with writing a proprietary tool to edit the database themes and subsequently with an expensive rewrite to extract all the themes out of the database and into proper css files.
One typical reason to go down the path of putting styles in the database tends to be a desire to allow a given style to be "overridden" on a case-by-case basis - for instance, in an application service provider model, where one customer wants to change only one or two of the default styles. However, the "cascading" in "cascading style sheets" allows this exact behavior, without abandoning all the goodness of proper css and the associated tools - as long as you sequence the stylesheets in the correct order in the page head (e.g. "maintheme.css" first, then "customerX.css"), you only need to redefine the styles of interest in the customer's stylesheet and they will automatically override those in the main theme's stylesheet (assuming the css selectors otherwise have the same precedence).
A related, but slightly different reason given for going with database-driven stylesheets is to allow end users or business owners to edit the styles themselves. With a few exceptions, that sort of feature turns out to be less used and more difficult to maintain in practice than it seems when drawing it up. In this case, the number of styles being customized is theoretically quite small - presumably entirely constrained - and you'd be writing a proprietary tool to allow them to be edited, regardless, so again I would suggest simply writing out the customized styles to a css file on a filesystem, rather than a database (or as a blob to a CDN, etc.).

Merge items in nanoc

I have been trying to use nanoc for generating a static website. I need to organize a complex arrangement pages I want to keep my content DRY.
How does the concept of includes or merges work within the nanoc system? I have read the docs but I can't seem to find what I want.
For example: how can I take two partial content items and merge them together into a new content item.
In staticmatic you can do some like the following inside your page.
= partial('partials/shared/navigation')
How would a similar convention work within nanoc?
nanoc’s author here.
In nanoc, partials are layouts. So, you could have layouts/partials/shared/navigation.html and then render that partial like this:
= render '/partials/shared/navigation'
For that to work, enable the Rendering helper first, by including it somewhere in the lib/ dir (e.g. lib/helpers.rb):
include Nanoc3::Helpers::Rendering
For more information, check out the layouts as partials section of the manual.
Hope this helps!

Resources