loading scripts in a defined order in rails app. how to? - ruby-on-rails

I noticed that some jquery effects requires that scripts are loaded in proper order.. in my case it is working if they are loaded like this:
jquery 1.4.4
jquery-ui-1.8.16.custom.min.js
autocomplete-rails.js
jquery.cycle.all.js
....
if they load in different way then some of my animation or jquery feature is not working. So how do I specify in rails wich script to load first?
Right now I did it in a primitive way by adding 1 2 3 numbers in front of names of every script I have in order that I need resulting in:
1jquery 1.4.4
2jquery-ui-1.8.16.custom.min.js
3autocomplete-rails.js
4jquery.cycle.all.js
It's primitive but it's working. Is there another way of doing it?
Rails 3

For Rails 3.0:
javascript_include_tag takes an array of sources, and includes them in the order that you define. You can omit :defaults, or define it in your application.rb file with config.action_view.javascript_expansions[:defaults] = %w(foo.js bar.js). :all includes all the javascripts in your /javascripts/ folder.
Therefore, it's best to have jQuery at the beginning, since most or all of your javascript files will use jQuery.
More documentation: http://apidock.com/rails/ActionView/Helpers/AssetTagHelper/JavascriptTagHelpers/javascript_include_tag

Related

Where in the Rails framework should I place my Backbone templates?

I'm a rails developer trying to learn Backbone and then I ran into this problem: since Underscore templates include symbols like <%=%>, I guess templates can't be included into erb files, so is it okay to have a rails partial for every single template? And what extension should it be?
You can escape the erb symbols by using two % in the opening tag, and put your backbone templates in the rails views:
<script type='text/template' id="my-template'>
<%%= name %>
</script>
will output the following in your page:
<script type='text/template' id="my-template'>
<%= name %>
</script>
Putting your Backbone templates directly in your rails views is IMHO the best option when you're trying to learn. You're already wrestling with the new concepts, no need to add another hurdle.
Starting with Rails 3.1, it provides two things that make working with Backbone templates a little easier: the asset pipeline, and automatic JST (JavaScript Template) compilation.
Create a directory in your app/assets folder called templates. This directory will automatically be picked up by the asset pipeline.
Next, name the files in that directory with an extension of jst and the type of template you are creating ejs (embedded javascript). You can even nest them in directories. For example:
app/assets/templates/my_template.jst.ejs
app/assets/templates/bookmarks/show.jst.ejs
The asset pipeline also allows you to use other templating languages like embedded coffeescript, mustache, handlebars, etc. by simply changing the file extension (and including any necessary gems).
Now to reference your JST templates in your Backbone views, simply use the path to the filename:
var Bookmark = Backbone.View.extend({
template: JST['bookmarks/show'],
render: function() {
this.$el.html(this.template(this.model.attributes));
return this;
}
});
You may need to add this line to your application.js:
// require_tree ../templates
Here's a nice article which explains all of this in a little more detail: http://www.bigjason.com/blog/precompiled-javascript-templates-rails-3-1
Where should you put your Backbone templates? I'd say nowhere. I believe that in most Rails applications, the server should be responsible for all rendering of HTML, while the client-side JavaScript should just be responsible for inserting that rendered HTML into the DOM. Among other things, this makes I18n easier.
The exception would be if Rails is simply being used as a lightweight backend for an application that runs mostly on the client side (though in that case, you might want to use Sinatra or something instead). In this case, Rails should probably render nothing, and have the JS do all the rendering.
Notice the underlying principle here. Either the server should be responsible for all rendering, or the client should. Splitting it will make life harder.

Dynamic (S)CSS in rails 3.1

I'm trying to allow the user to customize my application using YML files.
When the user updates certain things the CSS needs to be updated as well.
I'd like to solve this problem using dynamic CSS instead. The way I was planning on doing this is to have a settings SCSS file which the other css files import and use.
Here is what I have so far:
settings.scss.erb:
$width: <%= Rails.application.config.width %>px;
main.css.scss:
//= require settings
#import "settings";
#main {
width: $width;
}
But I get this error:
Invalid CSS after "$width: ": expected expression (e.g. 1px, bold), was "<%= Rails.appli..."`
So It seems that the settings are not being passed through the erb parser before being handed off to the SCSS parser, is there any way to solve this.
I'd rather not put everything in .erb files since my text editor doesn't support (syntax highlighting and commands) when having scss in erb files
Side stepping the problem where ERB is not being parsed, you are not going to be able to customize the CSS dynamically (I think the main file may require an erb extension). The asset pipeline is designed to serve assets in a way that tells browsers that the are static and are not going to change.
Assuming the erb parsing was working, the width would be rendered during the precompile phase, or on the first request. If you are using Sprockets far-future headers are set to tell the remote clients to cache the content for 1 year. And Sprockets only picks up changes if the timestamp of the file changes, so would never get any new values.
You could force Sprockets to dynamically serve every request, and to not send any headers, but it is not really designed for this and there are significant performance risks in doing so.

Rails Asset Pipeline: Precompile Assets outside of manifest?

I have certain page-specific js and css files that I either:
Don't want running on development (ie tracking code)
Don't want running on every page
or both.
In Rails 3.0.x I would simply call them from the view where they are needed like so:
- if some_condition
= javascript_include_tag 'page_specific'
Now, using the asset pipeline, it looks like I must include these in the manifest (and therefore in every page for the application) or else they won't be precompiled. As I'm using Heroku for deployment allowing lazy compilation is not an option.
How can I manually precompile every file from the assets directory without having to include them all in the manifest? Is this possible?
Just don't put the page specific asset in the manifest and include them when you need it like you did in rails 3.0.x, the precompiler will compile those page specific as separate files.
Personally I just check for a certain element I know is in the dom in that page. If the element isn't found the rest of the code isn't executed.
$(function(){
if( $("#page_specific_element").length !== 1 ) return;
//page specific functions
});

How can I access Rails objects in Sass?

In a Rails 3.1.0 project, I have Companies with a few customizable attributes like background_color and link_color. I want to be able to set some Sass variables like so:
$background_color: <%= #company.background_color %>
$link_color: <%= #company.link_color
...
This doesn't work because #company is nil when Sass does its thing. I'm not sure how to go about solving this in a way that's dynamic (companies can be created and colors can be changed and the views update immediately). Any suggestions?
I can think of a couple approaches off the top of my head:
Serve your stylesheet through a controller.
Use CSS classes to configure the colors and serve just that CSS through a controller, inlined partial, or a CSS #import.
Serving your stylesheet through a controller is pretty straightforward so there's not much to say. This might be a bit ugly and cumbersome.
For the second one, you'd add a couple extra CSS classes:
.custom-bg {
background-color: some-default-bg;
}
.link-fg {
color: some-default-fg;
}
/*...*/
Then any element that need to use the custom background color would need their usual CSS classes and custom-bg; similar shenanigans would be needed for the other configurable values. To supply the customized CSS, you could inline a <style> element into your HTML using a standard ERB partial or you could serve the CSS through a controller (either through <style src="..."> or #import). So you'd fake the SASSy goodness with old school multiple CSS classes in your HTML.
There's also JavaScript. You'd need some way to identify the elements that need their colors adjusted and then adjust them directly with things like this:
$('.need-custom-background').css('background-color', '...');
I think you might be able to do something just like what you have there, but you need to change the extensions of the files to '.css.scss.erb'
To follow up on this, I did create a stylesheet controller but it was rather contrived to get Sass parsing and asset pipeline load paths all working correctly. I ended up dumping that and reorganizing the styles so I could generate a static stylesheet for each company which gets regenerated and uploaded to S3 on company update.
Well, if you mean a dynamic object like a model loaded via a controller, you can't really, at least not very easily. This is because unlike HTML ERB templates, the SASS ones are generally rendered once and served statically unless something changes in the code or they are re-precompiled via rake (depending on your environment configs). But you can access some helper methods, global objects, and use some ruby in there by renaming the file with an "erb" extension e.g. application.css.scss.erb. See
https://guides.rubyonrails.org/asset_pipeline.html#coding-links-to-assets
How can I use Ruby/Rails variables inside Sass?)
If you need styles based on dynamically loaded objects, like models, you can...
Write CSS styles literally in the template
Compile the stylesheets dynamically. See the top-rated answer here: How do I create dynamic CSS in Rails?
For some use cases you might accomplish the same thing by leveraging Rails/SASS's import path hierarchy (i.e. SASS #import 'partial_name_with_no_path' will search the importing SASS files folder first and then fall back to the top level - You can configure this as well).

Why does rolling up javascript or css in rails screw with the layout?

On a few occasions now when I've moved from development to staging, I've been bitten by how JavaScript and stylesheets change their behaviour when rolled up into a single file.
For example, I'm trying to keep the series of stylesheets modular and small for maintainability, like so:
<%= stylesheet_link_tag "reset-fonts-grid.css", "typography.css", "layout.css", "cms.css", "cms.about.css", "cms.legal.css", "comments.css", "user_generated_content.css", "overlay.css", "login_page.css", "flag_for_admin.css", 'patch.css', 'nag_guide.css', :cache => "cache/all" %>
The works fine in development, when you're more concerned with debugging than counting http requests.
But as soon as I move to a production environment or set caching to be on in config/environments/development.rb like below, the layouts break:
config.action_controller.perform_caching = false
What's going on here, and why would a concatenated file behave differently to series of smaller requests like this, and how can I fix this?
As an aside, how much of a difference does the number of http requests actually make on page, compared to file size?
Does your CSS validate? I have had problems in the past similar to yours which were caused by small errors that I found with validation.
Try http://jigsaw.w3.org/css-validator/
Out of interest, does it work if you change your :cache option so that it doesn't include a forward slash? For example:
<%= stylesheet_link_tag "reset-fonts-grid.css", ..., :cache => "foo" %>
What does the HTML link element look like that Rails is generating for your combined stylesheet?
If you want to dig into the details of how the styles are being applied in the concatenated vs. the non-concatenated situation, you can install the FireBug plugin for Firefox. Then maybe open up two browser windows, one with the page in dev and one in production and use FireBug to isolate one DOM element that's giving you trouble and compare the calculated CSS attributes for that element in the two different situations.
The latest version of Safari has a built-in tool that is very similar to FireBug.
Is it possible that Rails is concatenating the CSS files in an incorrect order? Seems unlikely, but perhaps there's a bug in Rails. Take a look at the concatenated file and check the order. If they're out of order, you could create one master CSS file and include the others with #include statements. That would ensure that they're read in the correct order.

Resources