3

I have several javascript (coffee script) files in my Rails javascripts directory. The code is logically divided into different files. However, each file starts with $(document).ready -> and some files share common helper functions.

What is the best way to factor out the helper functions? Should I just put them all in some other file that gets included earlier in application.js?

Also, is it normal to have the code divided up the way mine is, where every page does $(document).ready ->? Doesn't this mean that all of my code is called on every page, regardless of whether or not it is relevant? Are there alternatives to this organization?

I'm not sure if this question is specific to Rails or relevant to javascript and jQuery in general.

mushroom
  • 6,201
  • 5
  • 36
  • 63

1 Answers1

2

I do think this is a Rails question, and a good one.

The normal paradigm in Rails, where "global" stuff goes in application.* is a little messed up with the asset pipeline, since the application.js really acts as a manifest, rather than a common file. Of course you could add stuff there, or even create an application.js.coffee for your common code. I decided to create a file called common.js.coffee (and in another case shared.js.coffee), which in my case was automatically handled by the require_tree . directive.

(Update based on comment from @jonathan-tran) In some cases, you may just want methods called on document ready for all pages -- for example, I used this to make a datepicker available to any field in any view. If, instead you want methods (actually global functions) available to be callable, you'll need to export the coffeescript functions to variables, for example by attaching to the window object. You can do both in a shared file.

It is true that if you use generators you'll end up with files for every controller which, if there's no specialized code result in a series of redundant $(document).ready -> statements when assets are compiled. So just get rid of the ones you don't use. But following the pattern of separating functionality specific to a page makes good sense to me and works well -- I know where to look to find stuff and that's worth a lot as a project grows.

And another rule I have learned with Rails: go with the flow. If that's how Rails does it, it's probably a good way. They do indeed think about these things. Don't fix what works :-)

Tom Harrison
  • 13,533
  • 3
  • 49
  • 77
  • For some reason, I am having issues getting the common file to work. The files that depend on it can't see the common functions. I have the common file above the files that depend on it in the manifest. //= require_tree . is at the bottom. Any ideas? So I have: //= require common //= require dependencies //= require_tree . – mushroom Nov 28 '12 at 02:44
  • 2
    That's because the CoffeeScript compiler wraps every entire file in a function so that variables do not leak. If you want a function or variable to be globally accessible, you need to explicitly export it. The easiest way to do this in a browser is `window.foo = blah`. See [this question](http://stackoverflow.com/questions/5211638/pattern-for-coffeescript-modules) for more info. – Jonathan Tran Nov 28 '12 at 02:51
  • @JonathanTran Yes, that was the issue. Thanks. – mushroom Nov 28 '12 at 02:56