Hard-coding IDs

Should HTML DOM IDs be hard-coded throughout a Rails app, or stored
within..an appropriate model or helper or ..?

Here's an example problem:

/neighbourhoods/1/map/ has a form:
  # map.html.erb
  <% form_remote_tag ... :html => {:id => 'map-filter-form'} do %>

When the page loads, the form needs to be submitted:
  # public/javascript/submit_map_filter_form.js
  Event.observe(window, 'load', function() {

Thus, I include the Javascript file mentioned above:
  # map.html.erb
  <%= javascript_include_tag 'submit_map_filter_form' %>

This feels wrong because the form's DOM ID ("map-filter-form") is hard-
coded in multiple locations (the view, and the Javascript file). As I
add functionality that uses the form, the number of places where the
form's DOM ID is hardcoded will increase.

Does anyone have suggestions or comments for how to deal with this?


One solution I can think of is to put the DOM ID into an appropriate
model. In this case, I'd make RentalMap#map_filter_form_dom_id return

However, if I do that, the contents of submit_map_filter_form.js would
need to be placed elsewhere, because RentalMap#map_filter_form_dom_id
can't be called from the Javascript file.

I could do something like this:

Add a class method to the RentalMap model for the DOM ID:
  # rental_map.rb
  class RentalMap
    MAP_FILTER_FORM_DOM_ID = 'map-filter-form'

    def self.map_filter_form_dom_id

The form in /neighbourhoods/1/map/ calls the new method:
  # map.html.erb
  <% form_remote_tag ... :html => {:id =>
RentalMap.map_filter_form_dom_id} do %>

Move the Javascript into a partial so that the new method can be
  # _submit_map_filter_form.html.erb
  <script type='text/javascript'>
    Event.observe(window, 'load', function() {
      $('<%=h RentalMap.map_filter_form_dom_id -%>').onsubmit();

The partial above must be rendered:
  # map.html.erb
  <%= render :partial => 'submit_map_filter_form' %>

But that doesn't feel right, for several reasons:
1) Now there's a partial whose sole purpose is to spit out some
Javascript code (as opposed to HTML code).
2) The form's DOM ID doesn't feel like it belongs in a model in the
first place.
3) As the number of DOM IDs that shouldn't be hard-coded increases,
the models get filled up with these tiny methods.

I'd love to hear any comments and suggestions you guys have. Thanks!

When it comes to HTML... it's kind of hard to not... hard-code it.
Either you end up having some dictionary that is a pain to manage or
you just have good conventions.

This is what we do at Planet Argon to keep things a bit more organized.

* http://www.robbyonrails.com/articles/2007/08/01/designers-developers-and-the-x_-factor

Good luck!


Hi Robby. Thanks for the link and for sharing those conventions. The
idea you guys decided upon definitely helps mitigate problems that
involve renaming IDs.

Hard-coding the DOM IDs still doesn't sit right with me, though. It
feels like the string-version of "magic" numbers, which was beaten out
of me many, many years ago =P

Thanks again,

By the way, did you write a follow-up to the blog post above? I looked
through your archives and a couple of tags, but didn't find it.

For anyone else who finds this thread...

There's a plugin called "embedded javascripts":

In a nutshell, it defines ActionView::Base#include_javascript , which
takes the name of a Javascript file as an argument, processes any ERB
in the JS file, and returns the JS code sandwiched between <script
type="text/javascript" ..> and </script>.

That sounds like a good tool to use in a solution for the originally-
stated problem. However, it doesn't feel right to me. The Javascript
file will never be cached by browsers, and it adds another call to
read from the file system, which will slow things down a bit. However,
for a small app, I think it's a great tool.

Dan Webb released two plugins - MinusR and MinusMOR - with the latter
being an update of the former:

I like MinusMOR, as it doesn't hijack the .rjs file extension.
However, I don't think it's a tool that could [easily] be used to
solve the original problem. But it's still a pretty cool plugin!

In the end, I've decided to hard-code HTML elements' DOM IDs in views,
partials, RJS templates, Javascript files, and wherever else. On top
of that, every element that is touched by Javascript will have its DOM
ID prefixed with "x_". This will make it very clear which elements'
DOM IDs shouldn't be changed on a whim.

What I've just explained is Robby Russell's approach. He explained it
quite well in a blog post: