Rails and Javascript - don't mess with the client

8 views
Skip to first unread message

Stefan Klein

unread,
Dec 20, 2007, 5:37:50 AM12/20/07
to rubyonra...@googlegroups.com
I am new to the list and Rails (and Ruby, for that matter) and whilst
I was a bit skeptical due to the hype it's causing, I am starting to
really like it and there seems to be a really active and friendly
community behind it which is an added bonus.

I have been writing web applications for a while now using different
languages and frameworks (including hand-written ones just following
best practices). I like it how Rails combines a lot of best practices
and how its conventions guide the user to writing good applications
(which I am convinced is possible on any kind of platform, but you
need to know what you're doing, whilst Rails often takes you by the
hand and stops you from getting off track).


One thing I am having serious doubts about, though, is the usage of
JavaScript in Rails and I would appreciate your comments on my
thoughts. I hope this hasn't been discussed before, I did my best to
try and search for comments on it, the only thing I did see mentioned
was an article by Dan Webb about Ruby being the devil on the client-
sides shoulder, but it seems to have been taken off the web.

There is two things I would like to comment on:
1. How Rails creates a mess on the client-side violating the MVC
2. Why I don't see the use of RJS


1. How Rails creates a mess on the client-side violating MVC
Whilst this has often been obscured by messy coding practices, you
can easily think of the client side of a web application as
implementing the MVC-paradigm.
M: HTML is the model. Good HTML does not include any presentational
information. (e.g. that is why nowadays there is a wide consensus
that HTML-tables are not meant to be used for layout)
V: CSS is the view. It defines how HTML data is presented on the
screen. I admit that a certain part of the presentation is pre-
defined by the ordering within the HTML, but stylesheets still allow
you to fundamentally shape a page
C: JS is the controller. It defines the beaviour of elements on the
page and in more advanced applications (especially AJAX) it
manipulates the HTML data.

However, HTML allows you to break the paradigm. You can include CSS
in your HTML (using style-tags) and you can include JS in your HTML
(using onclick, onmouseover etc. event-handler-tags). The fact that
MVC is so pervasive on the server side these days seems to indicate
that it has some value, though. So you can mess it up on the client
side but, as with any best practice, you usually realise after a
while that you're better off when you don't.
It's become very common practice to keep your CSS out of your HTML.
For JS however, there is still a lot of mixing going on as it seems.
However, it is easily possible to keep your Javascript entirely out
of your HTML. The approach is often termed Unobtrusive JavaScript
(UJS). Sounds like a new feature, but essentially it's just doing
what should always have been done. There is very good libraries
supporting it such as prototype and lowpro (especially its behaviour
feature).

Now, coming to Rails: On the server side it provides a very clean
implementation of MVC, strictling separating the three components. On
the client side, however, Rails creates a considerable mess on the
client side by heavily mixing Javascript into HTML (especially
promoted by RJS), thus mixing V and C. From the server's point of
view HTML, JS and CSS are all part of the view. Fair enough. But from
the client's point of view they're not.

An attempt has been made by Luke Redpath and Dan Webb by providing
the UJS plugin (http://www.ujs4rails.com/). However, Dan lines out
himself that it is a somewhat half-hearted attempt (http://
www.danwebb.net/2007/6/16/the-state-and-future-of-the-ujs-plugin) The
plugin may create cleaner code in the end and may save you band-width
by keeping your JS out of your HTML (thus having to download it once
only). But to my mind, UJS is above all about programming practice,
about clean and maintainable code and the plugin doesn't help that.


2. Why I don't see the use of RJS
I have spent a fair amount of time pondering about it, I have read a
lot of enthusiastic tutorial, but still I fail to see the use of RJS.
Essentially, RJS provides Ruby functions that output some bits of JS
code. Such as other functions (for example the form helpers, I hope I
am using the right terminology here) output HTML.
In terms of HTML that makes sense. HTML is a markup language, not a
programming language. There is no way to write functions, makros or
whatever in HTML. So if you have a certain complex HTML-construct
(e.g. a complex table or a custom control made up of various tags),
you would have to write it by hand again and again. So it's useful to
have a Ruby function that does the job and reduces the work to a
single line of Ruby instead of say 20 lines of HTML.
However, JS is a programming language. If there is something complex
that you expect to be doing in many places, you can write a
Javascript function. So why do I need a Ruby function that renders
three lines of Javascript where I can just have a Javascript function
that reduces the three lines to one function call. Even more so, why
do I need a Ruby function like page.hide that translates to a single
JS call Element.hide.

That doesn't make your code DRYer, it doesn't make life easier. Yes,
I know, it saves you from writing JS. But JS is not difficult and
there are brilliant libraries and it's well worth the effort of
learning. Because what price do you pay using RJS the way I see it
used most of the time?
- It creates an extra layer of complexity. It wraps Javascript with
Ruby (in a way you can think of RJS as compiling Ruby to Javascript).
- it seems to me that with any serious JS-based application you will
quickly run into the limitations of RJS and you will need real JS,
anyway (Dan Webb seems to think along similar lines: http://
www.danwebb.net/2006/11/17/rjs-minus-r)
- when it comes to debugging you will still have to do it on the
client-side. You won't recognize your own code, because you wrote it
in Ruby, but what you're looking at, now, is JS. Firebug is a very
powerful and useful tool for debugging. But you will have to work in
Javascript. And you're life will be much easier if your code is well-
structured within one JS-file and not spread out all over the place
inside HTML, in JS-files and in RJS-files that are downloaded using
AJAX on demand. That is a nightmare to debug.

So for the moment, for my first Rails project, my approach will be:
I will use Rails for the server side and I won't let it mess with the
client-side. Rails belongs to the server and that's where it's
brilliant. For the client, there is HTML, JS and CSS already and used
properly they can be brilliant in their own way. I will treat JS just
as CSS: I will put it in the public folder and write only clean UJS
using prototype and lowpro which make it dead easy. I will debug
using Firebug on the client side.
I am thinking about writing my own version of
"javascript_include_tag :defaults". My version would not only include
the default scripts but would also check if there is a js-file by the
same name as the controller in /public/javascripts. So /app/
controllers/user_controller.rb would have a corresponding /public/
javascripts/user.js that represents the client-side controller and is
included whenever a resource within the user controller is requested.


I am very keen on hearing your comments! Thanks
Stefan

Michael Schuerig

unread,
Dec 20, 2007, 7:24:40 AM12/20/07
to rubyonra...@googlegroups.com
On Thursday 20 December 2007, Stefan Klein wrote:

> 1. How Rails creates a mess on the client-side violating MVC
> Whilst this has often been obscured by messy coding practices, you
> can easily think of the client side of a web application as
> implementing the MVC-paradigm.
> M: HTML is the model. Good HTML does not include any presentational
> information. (e.g. that is why nowadays there is a wide consensus
> that HTML-tables are not meant to be used for layout)
> V: CSS is the view. It defines how HTML data is presented on the
> screen. I admit that a certain part of the presentation is pre-
> defined by the ordering within the HTML, but stylesheets still allow
> you to fundamentally shape a page
> C: JS is the controller. It defines the beaviour of elements on the
> page and in more advanced applications (especially AJAX) it
> manipulates the HTML data.

You're hijacking the MVC pattern. Your argument is essentially this

- MVC is good
- I can map M, V, and C onto separate languages used on the client
- Therefore, this separation on the client is (or would be) good

I'm not saying that a separation of structure, presentation, and
behavior is not good. It can be very good indeed. But this is not
because it can be mapped contortedly onto MVC.

MVC is good for reason, namely that is resolves several forces in
favorable ways. For your argument to hold, you'd have to demonstrate
that these same forces apply to the targets of your MVC and that they
are resolved equally favorable.

> However, HTML allows you to break the paradigm. You can include CSS
> in your HTML (using style-tags) and you can include JS in your HTML
> (using onclick, onmouseover etc. event-handler-tags). The fact that
> MVC is so pervasive on the server side these days seems to indicate
> that it has some value, though. So you can mess it up on the client
> side but, as with any best practice, you usually realise after a
> while that you're better off when you don't.

You don't have an argument here. It boilds down to praise by
association. Because MVC is good "there", doesn't imply that it is good
elsewhere.

> Now, coming to Rails: On the server side it provides a very clean
> implementation of MVC, strictling separating the three components. On
> the client side, however, Rails creates a considerable mess on the
> client side by heavily mixing Javascript into HTML (especially
> promoted by RJS), thus mixing V and C.

You're missing one essential point. You fail to distinguish between
between structure/presentation/behavior as they exist in views and
HTML/CSS/JS as they are or not mixed-up in generated web pages.

This distinction is crucial. And it is, of course, a Rails best
practice, to keep behavior out of views and put it in helpers or
controllers. At its root, this is just separation of concerns.

Your complaint about Rails apparently boils down to the fact that
the "compiled" output mixes concerns. There are independent arguments
why this may not be good, but you don't touch them.


> 2. Why I don't see the use of RJS
> I have spent a fair amount of time pondering about it, I have read a
> lot of enthusiastic tutorial, but still I fail to see the use of RJS.

I think you're discarding the enthusiasm of others too easily. You seem
to imply that they are misguided in seeing a use in RJS when you don't.

> Essentially, RJS provides Ruby functions that output some bits of JS
> code.

[...]


> Javascript function. So why do I need a Ruby function that renders
> three lines of Javascript where I can just have a Javascript function
> that reduces the three lines to one function call. Even more so, why
> do I need a Ruby function like page.hide that translates to a single
> JS call Element.hide.

I think the answer is obvious: Because it is a Ruby function, not a JS
function.

> That doesn't make your code DRYer, it doesn't make life easier.

Well, it makes life immensely easier for those Rails developers who
don't know JavaScript.

> Yes,
> I know, it saves you from writing JS. But JS is not difficult and
> there are brilliant libraries and it's well worth the effort of
> learning. Because what price do you pay using RJS the way I see it
> used most of the time?

So, all Rails developers have to learn JS because it is easy and simply
relying on their framework to do it's part is somehow making them pay a
price that they don't perceive.

> - It creates an extra layer of complexity. It wraps Javascript with
> Ruby (in a way you can think of RJS as compiling Ruby to Javascript).

For those who don't know JS, it is a layer of simplicity.

> - it seems to me that with any serious JS-based application you will
> quickly run into the limitations of RJS and you will need real JS,
> anyway (Dan Webb seems to think along similar lines: http://
> www.danwebb.net/2006/11/17/rjs-minus-r)

Don't do a "serious JS-based application" with RJS. That's no-brainer.
Don't do anything that seriously involves X unless you know X well
enough.

> - when it comes to debugging you will still have to do it on the
> client-side.

The beauty is that for most common uses of RJS you rarerly ever have to
debug. If someone runs into this regularly, they are using RJS well out
of its scope. The others may go ahead.


> I am very keen on hearing your comments! Thanks

I'm quite sure that what I wrote is not what you'd hope to hear. I'm
adversarial on purpose because I agree with some of your conclusions,
but I'm convinced that your arguments don't pull their weight there.

First and foremost, your arguments suffer from absolutism. You imply
that because something is not good for your purpose it can't be good
for any purpose. In the case of RJS this is patently not true.

Regarding unobtrusive JavaScript, you'd have to argue what tangible
advantages it brings for developers or users. Prima facie, it makes
thinks more contorted for developers, for they can't just attach
behavior where it applies. Maybe this can be offset by improved
accessibility and graceful degradation, but these don't come free even
with unobtrusive JS.

For the record, I know JS fairly well and like to use it. But I
recognize this as a minority position among software developers (aka
backend programmers).

Michael

--
Michael Schuerig
mailto:mic...@schuerig.de
http://www.schuerig.de/michael/

Phillip Koebbe

unread,
Dec 20, 2007, 8:25:49 AM12/20/07
to rubyonra...@googlegroups.com

On Dec 20, 2007, at 4:37 AM, Stefan Klein wrote:

> I am thinking about writing my own version of
> "javascript_include_tag :defaults". My version would not only include
> the default scripts but would also check if there is a js-file by the
> same name as the controller in /public/javascripts. So /app/
> controllers/user_controller.rb would have a corresponding /public/
> javascripts/user.js that represents the client-side controller and is
> included whenever a resource within the user controller is requested.
>

I did not replace javascript_include_tag, but I do use a global array
called @js_includes, and in my layout, I do something like

<% if @js_includes %>
<% @js_includes.each do |js| %>
<%= javascript_include_tag js %>
<% end %>
<% end %>

Then in my controller, I will do one of two things:

1) for js that applies to certain actions, include the js in the
action with

def my_action
@js_includes = ['my_js']
...
end

2) if the js applies to the whole controller, write a before_filter

before_filter :set_includes

private
def set_includes
@js_includes = ['my_js']
end

[Hm, now that I think about it, I should probably use the
before_filter all the time and tack on :only or :except. That'd be a
bit more DRY.]

I have not needed the flexibility yet, but I could also adjust my
assignment lines

@js_includes = ['my_js']

to be

@js_includes << 'my_js' unless @js_includes.include?('my_js')

I have done the same thing for CSS, but as I learn more about CSS,
I'm finding that this approach it is not as necessary.

Peace,
Phillip

Stefan Klein

unread,
Dec 21, 2007, 9:30:17 AM12/21/07
to Ruby on Rails: Talk
> I think you're discarding the enthusiasm of others too easily. You seem
> to imply that they are misguided in seeing a use in RJS when you don't.

It seems like I didn't manage to get my point across. What I was
hoping to express is that I can see the enthusiasm, but do not
understand it, so I am thinking there might be a point that I am
missing. That's why I wrote the post after all. If it was just to
complain I could have saved my time and do things differently myself,
after all, I do have an approach that I am happy with myself for the
moment.

But when so many people think it's a good thing, it a least deserves
to be looked at more deeply, I think. So I was hoping for people to
contradict and - unlike your expectation - your post was very much
what I was hoping for and I hope there will be others.

And if you are telling me that one of the main reasons behind RJS is
that people prefer to not write JS, then that explains the enthusiasm
and it helps me in taking my own decision that I personally don't need
RJS. So honestly thanks for that!

I am not trying to say MVC is good, because it's MVC. It's the same
reasoning as above: I see it used very widely by many people, I have
used it and until now always to my advantage. What we do and think is
a result of our experience, I guess. So far I have made good
experiences with MVC, so I believe it's a good thing. I haven't heard
strong arguments against it yet, but if you have any, I am more than
happy to hear them.
I am keeping my JS out of my HTML, because it makes it easier to reuse
code, I can apply the same behaviour to different markup. I can simply
link in a JS file to an HTML file without having to touch any of the
markup at all. I can even move my JS between projects using different
platforms. It doesn't matter whether the server part of my web app
runs on php, rails, some java framework or whatever. They can all
statically serve the JS file and it will work as long as they produce
the same markup.
Also it makes it easier to debug using Firebug when I have a single
clean JS-file and don't have to jump around between HTML-tags and JS-
files. Finally I like it when things are cleanly separated.

> but I'm convinced that your arguments don't pull their weight there.

Same goes here. If you do have any arguments, it'd be nice of you to
share them. It's exactly these arguments that I was hoping for.

> First and foremost, your arguments suffer from absolutism.

Only for the sake of simplicity (of my statements) and to call for
counter-arguments. Maybe I overdid it a little this time.
Thanks for replying in spite of that, Michael!

Stefan

Stefan Klein

unread,
Dec 21, 2007, 9:33:13 AM12/21/07
to Ruby on Rails: Talk
Thanks for sharing your approach Phillip. I might use that, too, and
it'll save me overwriting js_include_tag.

stefan

Michael Schuerig

unread,
Dec 22, 2007, 8:22:34 AM12/22/07
to rubyonra...@googlegroups.com
On Friday 21 December 2007, Stefan Klein wrote:

> I am not trying to say MVC is good, because it's MVC. It's the same
> reasoning as above: I see it used very widely by many people, I have
> used it and until now always to my advantage. What we do and think is
> a result of our experience, I guess. So far I have made good
> experiences with MVC, so I believe it's a good thing. I haven't heard
> strong arguments against it yet, but if you have any, I am more than
> happy to hear them.
> I am keeping my JS out of my HTML, because it makes it easier to
> reuse code, I can apply the same behaviour to different markup. I can
> simply link in a JS file to an HTML file without having to touch any
> of the markup at all. I can even move my JS between projects using
> different platforms. It doesn't matter whether the server part of my
> web app runs on php, rails, some java framework or whatever. They can
> all statically serve the JS file and it will work as long as they
> produce the same markup.

These are all good reasons, but they have nothing to do with MVC. Call
it separation of concerns, if you will. In true MVC, the model has a
very active role, it encapsulates state and its associated behavior.
Plain HTML markup is lifeless structure. If you insist on making it
into a model, you can add model behavior to it using JavaScript. Then,
on top of that, you can add presentational behavior and call it
controller or presenter if you go for MVP.

JavaScript in itself is not "the controller". It's a means of
implementing behavior. The interesting distinction is whether this
behavior is part of the business logic (model) or presentational
(view/controller).

> Also it makes it easier to debug using Firebug when I have a single
> clean JS-file and don't have to jump around between HTML-tags and JS-
> files. Finally I like it when things are cleanly separated.

When you insist that everything you're doing is so very clean, you're
implying that what others do differently is in some way dirty. Think of
it.

> > but I'm convinced that your arguments don't pull their weight
> > there.
>
> Same goes here. If you do have any arguments, it'd be nice of you to
> share them. It's exactly these arguments that I was hoping for.

Please read again what I wrote previously. Consider my comparison of
generated HTML/JS with the output of a compiler. Consider how state,
behavior, and presentation are separated in the representation the
developer is working on (models, view, controllers, helpers, ...) and
how they are separated -- or not -- in the result generated by a
template engine. I say that it is the separation of concerns in the
source representation that counts. You're claiming that it has to be
present in the generated result.

If you don't appreciate the distinction I make in the previous
paragraph, it won't make much sense for me to continue the discussion.

Your argument for separation of concerns in the output is that it gives
you better modularity:

> I am keeping my JS out of my HTML, because it makes it easier to
> reuse code, I can apply the same behaviour to different markup. I can
> simply link in a JS file to an HTML file without having to touch any
> of the markup at all. I can even move my JS between projects using
> different platforms. It doesn't matter whether the server part of my
> web app runs on php, rails, some java framework or whatever. They can
> all statically serve the JS file and it will work as long as they
> produce the same markup.

That's fair enough. Still, I can have the same advantages even if I'm
using RJS and other practices you abhor. Nothing keeps me from using
highly decoupled, unobtrusive scripts on top of that. But when it comes
to application-specific scripting, I'd like to use all the tools made
available by the framework, including RJS. No, I won't port that app to
PHP, certainly not.

Stefan Klein

unread,
Dec 22, 2007, 5:52:36 PM12/22/07
to Ruby on Rails: Talk
Michael,

I seem to be offending you in some way I cannot clearly grasp. I seem
to be giving you the impression that by stating my point of view I was
ruling out all others. From what I write you seem to read that me
having my own preferences somehow implies that I consider other
people's preferences as bad. Is that it?

I can only repeat that none of this is intended, but I am not sure
that will convince you, since I already tried to express that in my
last mail.

However, by now, I myself feel rather intimidated and judged unfairly
by your replies. I don't feel like I was given a chance. I don't feel
encouraged to keep on voicing my opinions (which I consider strictly
my opinions and that don't imply any deprecation of other people's
opinions). What can I say, if to you anything I do say seems to be
short-sighted, unjustified judgments or suffering from absolutism?

I talk about what I, Stefan, personally think, independently of other
people's opinions and without meaning to disqualify them. You
repeatedly judge and interpret my statements stating intentions that
you can merely guess. You do so using a rather forceful language: "if
you _insist_...", "if you _don't appreciate_..." "you're implying that
what others do differently is in some way dirty" (very clearly: no,
I'm not, I never said so and never meant to, it's your interpretation)

I don't feel my views respected, I feel judged unfairly and I feel
helpless trying to convince you that I am not intending what you are
perceiving. I cannot say where the problem lies, I tried, but it seems
I can't express myself clearly enough in this case. I don't feel this
is good grounds for further discussion, although I was hoping it would
be possible, as I really appreciated your initial reply.

Thank you for taking the time
Stefan

Michael Schuerig

unread,
Dec 22, 2007, 6:26:50 PM12/22/07
to rubyonra...@googlegroups.com
On Saturday 22 December 2007, Stefan Klein wrote:

> I don't feel my views respected, I feel judged unfairly and I feel
> helpless trying to convince you that I am not intending what you are
> perceiving. I cannot say where the problem lies, I tried, but it
> seems I can't express myself clearly enough in this case. I don't
> feel this is good grounds for further discussion, although I was
> hoping it would be possible, as I really appreciated your initial
> reply.

Most of the time I'm a really nice person and I didn't know that I could
be intimidating at all. That I'm responding rather forcefully has a
very specific reason: Our positions are probably not very far apart,
but I think you're doing it/them a disservice.

A case in point is your MVC analogy applied to HTML/CSS/JS. As I tried
to show before, it does not get off the ground. However, I do think
that there are good arguments for separation of
structure/presentation/behavior on the client-side *if* one is working
at that level. I'm not sure, and open to arguments either way, whether
the same forces and solutions apply at the higher level of Rails views.

If you'd like to discuss something less loaded, and as you are a
JavaScript afficionado, I'd appreciate your comments (in the proper
place) on this
http://schuerig.de/michael/blog/index.php/2007/12/22/javascript-fsm/
(yes, I'm a bit self-promotional here).

Corey Haines

unread,
Dec 22, 2007, 8:36:48 PM12/22/07
to rubyonra...@googlegroups.com
On Dec 22, 2007 6:26 PM, Michael Schuerig <mic...@schuerig.de> wrote:
> If you'd like to discuss something less loaded, and as you are a
> JavaScript afficionado, I'd appreciate your comments (in the proper
> place) on this
> http://schuerig.de/michael/blog/index.php/2007/12/22/javascript-fsm/
> (yes, I'm a bit self-promotional here).
>
> Michael

And I thought it was going to be a javascript flying spaghetti
monster! What was I thinking?

-Corey

Michael Schuerig

unread,
Dec 23, 2007, 4:18:18 AM12/23/07
to rubyonra...@googlegroups.com
On Sunday 23 December 2007, Corey Haines wrote:
> On Dec 22, 2007 6:26 PM, Michael Schuerig <mic...@schuerig.de> wrote:
> > If you'd like to discuss something less loaded, and as you are a
> > JavaScript afficionado, I'd appreciate your comments (in the proper
> > place) on this
> > http://schuerig.de/michael/blog/index.php/2007/12/22/javascript-fsm
> >/ (yes, I'm a bit self-promotional here).

> >
> > Michael
>
> And I thought it was going to be a javascript flying spaghetti
> monster! What was I thinking?

You... pirate! You!

Arrrr,

Fjan

unread,
Dec 23, 2007, 8:22:44 AM12/23/07
to Ruby on Rails: Talk
Stefan,

I largely agree with your points. The first point is addressed with
the new prototype library that is included with Rails 2.0, it provides
event observers that allow you to separate out the JS code from your
HTML entirely. (I would rather call it separation of concerns then an
MVC pattern to avoid confusion). Some of the rails helpers still spew
JS in your HTML but if that bothers you, you should be able to roll
you own.

The second point has also been a bit of a mystery to me: I haven't
come across anyone who actually uses RJS. All advanced web programmers
I know hand code their JS and also would not want to give up their
Firebug. If anyone has used it to good effect I'd love to hear about
it.

Cheers,
Jan
> himself that it is a somewhat half-hearted attempt (http://www.danwebb.net/2007/6/16/the-state-and-future-of-the-ujs-plugin) The  

Jan

unread,
Dec 23, 2007, 9:49:43 AM12/23/07
to Ruby on Rails: Talk
Hi Stefan,

Strongly agree with your point 2: one vote for JS here :)

Though I'm not a master on JS, I found it really easier to write JS
directly than use RJS when I tried Rails the first time. Learning the
use/api of RJS won't be obviously simpler than learning some JS.

And in Rails 2.0, we have a new powerful tool .js.erb!

Thanks,
Jan
> himself that it is a somewhat half-hearted attempt (http://www.danwebb.net/2007/6/16/the-state-and-future-of-the-ujs-plugin) The  

Stefan Klein

unread,
Dec 25, 2007, 4:45:32 AM12/25/07
to Ruby on Rails: Talk
Hi Jan + Jan,

thanks for both your views.

To FJan: Event observers in prototype? You're talking about the
prototype Event object? (I'm asking, because I thought that it has
been around for a while, but there might be something new that I
overlooked).

To Jan: Googling on .js.erb didn't come up with a lot of hits. I take
it this is Ruby embedded in JS along the lines of Dan Webb's MinusR
plugin?

To both of you: If you are using a lot of JS, what structure do you
use? Something like Phillip wrote earlier? One JS file per controller?
How do you serve/include your JS? For the moment, I like Phillip's
approach, maybe with an added convention that if there is a JS-file by
the name as the controller then it is included automatically without
having to be added to Phillip's global array.

Thanks
Stefan

Michael Schuerig

unread,
Dec 25, 2007, 7:58:30 AM12/25/07
to rubyonra...@googlegroups.com
On Tuesday 25 December 2007, Stefan Klein wrote:
> If you are using a lot of JS, what structure do you
> use? Something like Phillip wrote earlier? One JS file per
> controller? How do you serve/include your JS? For the moment, I like
> Phillip's approach, maybe with an added convention that if there is a
> JS-file by the name as the controller then it is included
> automatically without having to be added to Phillip's global array.

For the logical structure, I suggest a separation into generic/framework
code. Put generic code into an application object.

var Application = {
...
};

Then for each resource have an object or class. For example

var User = {
...
};

or

var User = Class.create({
...
});

Have these specific objects/classes be initialized/instantiated
appropriately. How? Two possibilities: Arrange it so that only the
relevant files are loaded per controller or write config information in
a script block in the header.

Michal Gabrukiewicz

unread,
Dec 25, 2007, 8:42:31 AM12/25/07
to rubyonra...@googlegroups.com
i am with you stefan .. i started developing ror 2 months ago and i
really like it. as you my first thoughts had to do with those rjs stuff
... now i see that its good for projects which hardly use javascript ..
but when it comes to more client side behavoir you are better of using
javascript directly by using the nice libraries out there ...

i like the idea of separating javascript by extracting the behavoir.. i
have no experience with it yet .. do you have a simple example of how to
do it for an autocompleter?
--
Posted via http://www.ruby-forum.com/.

Phillip Koebbe

unread,
Dec 25, 2007, 9:36:14 AM12/25/07
to rubyonra...@googlegroups.com

On Dec 25, 2007, at 3:45 AM, Stefan Klein wrote:

> To both of you: If you are using a lot of JS, what structure do you
> use? Something like Phillip wrote earlier? One JS file per controller?
> How do you serve/include your JS? For the moment, I like Phillip's
> approach, maybe with an added convention that if there is a JS-file by
> the name as the controller then it is included automatically without
> having to be added to Phillip's global array.
>

The reason I use a global array is to have a finer level of control
over what gets loaded when. I don't always do things the "proper"
way, so I will mix administrative actions in a controller with non-
administrative ones, then control access to them by a :require_admin
before_filter. I might be naive, but so far this has been working
out very well for me. In that situation, I might have some
Javascript that is specific to the administrative functions, so I
don't want it loaded if the user/action is not an admin. There might
be another way to accomplish this, but it has worked out well for me
to use the global array and assign the specific js or two action by
action.

On the other hand, if my JS applies to essentially all of the actions
in a controller, I can see how it would be DRYer to have a construct
that will automatically load a .js file with the name of the
controller. If for no other reason than to know how to do it, I
think will see if I can make that happen.

Thanks for sharing your thoughts, Stefan.

Peace,
Phillip

Stefan Klein

unread,
Dec 27, 2007, 9:36:58 AM12/27/07
to Ruby on Rails: Talk
To Michael G: if what you mean by autocompleter is something like a
date field that completes automatically, then here's your example. If
you are talking about something more complex like a field that offers
a list of suggested completions that is downloaded from the server via
AJAX, I think you will still get the idea which is the same.

Your HTML might be
<input id="date" type="text" value="Enter date here..." />

Then you could add some behaviour unobtrusively like this (providing
you use prototype and it's Event object, but the idea is independent
of it):

var input = document.getElementById("date");

Event.observe(input, 'focus', function() {
if (this.value == "Enter date here...") this.value = "";
});

Event.observe(input,'change',function() {
// some code to check that this.value is a valid date and
autocomplete it
});

Event.observe(input, 'blur', function() {
if (this.value == "") this.value = "Enter date here...";
});

I hope this is enough of an example to give you an idea. You can also
go one step further and use Dan Webb's behaviour code in lowpro. It
allows you to attach a behaviour to a CSS class rather than to an
individual id as above.

That way you could attach a behaviour to a CSS-class 'date' and then
add as many <input type="text" class="date"/> as you wanted to your
page and they would all expose the same behaviour without any extra
JS.


To Michael S:
>Have these specific objects/classes be initialized/instantiated
>appropriately. How? Two possibilities: Arrange it so that only the
>relevant files are loaded per controller or write config information in
>a script block in the header.

Possibility one is understood. Can you give an example for possibility
two, I am not sure I understand. How would you write that config
information so that only those objects/classes that are needed are
loaded from the server. Thanks.


To Phillip:
Thanks for the explanation. As far as implementation is concerned, I
was thinking that it should be fairly easy. I am not fluent enough in
RoR yet to provide a piece of code, but it should be possible in the
layout to get the name of the controller class?
Then I would just use your snippet and add an if-block that checks if
there is a js-file by the same name in /public/javascripts and if
there is, include it. If not, nothing. That keeps you flexible, no
need to create a js-file for each controller, but if you want to you
can, without having to add extra code.

I guess, it should also be possible to do the whole thing
using .js.erb instead of plain .js, so if you like you can use the
same structure and still embedd ruby into your javascript.
Which just brings me to a new idea: You could then have a ruby
function like "include_js" that you can call from your .js.erb and
that allows you to include further js-files (the function just adds
them to your global array that is then rendered in the layout just as
you do). I think I might like that, because that way javascript files
are included where they are used. I have always thought that it's not
very pretty to have to include your JS (be it libraries or just some
of your own objects you're making use of...) inside the HTML file
whilst they're being used inside other JS files. And as far as I know,
unlike CSS, JS doesn't allow any includes or imports, so in that
case .js.erb would really provide an extra feature, even for those
like me who like their plain JS.

Stefan

Michael Schuerig

unread,
Dec 27, 2007, 11:24:38 AM12/27/07
to rubyonra...@googlegroups.com
On Thursday 27 December 2007, Stefan Klein wrote:
> To Michael S:
> >Have these specific objects/classes be initialized/instantiated
> >appropriately. How? Two possibilities: Arrange it so that only the
> >relevant files are loaded per controller or write config information
> > in a script block in the header.
>
> Possibility one is understood. Can you give an example for
> possibility two, I am not sure I understand. How would you write that
> config information so that only those objects/classes that are needed
> are loaded from the server. Thanks.

That's not what I was trying to say. You could use one of the available
JS dependency mechanisms to load only the files that are needed; as far
as I can tell, these mechanisms all involve adding script elements to
the document head.

However, I had in mind something simpler entirely. For the kind of apps
I've been working on most of the time, I usually don't have a
collection of loosely coupled scripts adding this or that behavior to a
page. Rather, I have some fairly general framework code +
application-/resource-specific code + configuration.

I don't have a good example handy, but have a look at this page

http://www.schuerig.de/michael/webdesign/demo/form.html

and its linked scripts, in particular

http://www.schuerig.de/michael/webdesign/demo/javascripts/boilerplate.js

and in there the last few lines of BoilerPlate#baseInitialize.

Michal Gabrukiewicz

unread,
Dec 27, 2007, 2:07:29 PM12/27/07
to rubyonra...@googlegroups.com
thanks for the explanation ... i see what you mean and i may try this in
my next project ... there is still one question .. when is it best to
load UJS? in the head? .. i assume it must be done after the whole page
has been loaded..

Stefan Klein wrote:
>
> I hope this is enough of an example to give you an idea. You can also
> go one step further and use Dan Webb's behaviour code in lowpro. It
> allows you to attach a behaviour to a CSS class rather than to an
> individual id as above.
>
> That way you could attach a behaviour to a CSS-class 'date' and then
> add as many <input type="text" class="date"/> as you wanted to your
> page and they would all expose the same behaviour without any extra
> JS.
>
>

eggie5

unread,
Dec 27, 2007, 2:22:45 PM12/27/07
to Ruby on Rails: Talk
Very keen. I express the same qualms as you regarding rails generated
javascript. SO, in the end I just write the JS myself. It's actually a
pretty cool language!
Reply all
Reply to author
Forward
0 new messages