DRYing up link_to_remote for degradable URLs

I like to keep my links in my Rails applications that make AJAX requests degradable in non-JavaScript browsers so I often find myself doing this:


link_to_remote 'Show details',
  { :url => { :action => 'show', :id => post.id } },
  { :href => url_for({ :action => 'show', :id => post.id }) }

This allows me to get HTML links like so:


<a href="http://www.example.com/posts/show/123" onclick="...">Show details</a>

instead of the usual (if the :href parameter is not specified):


<a href="#" onclick="...">Show details</a>

You’ve probably already noticed the duplication right there in the :url key of the 2nd parameter (options) and the :href key of the 3rd parameter (HTML options) that litters my Erb templates where link_to_remote calls are prevalent. I got tired of editing and copying and pasting the url_for parameters so I monkey patched Rails’ PrototypeHelper class in ActionPack (actionpack/lib/action_view/helpers/prototype_helper.rb).

To do this, I had to replace Rails’ link_to_remote method definition. Thanks to living and breathing code examples in Rails that do this, I was able to promptly come up with this module that I placed into the lib/ directory of my Rails application and require it in my environment.rb file.


module Bezurk #:nodoc:
  module ActionView #:nodoc:
    module PrototypeHelperExtensions
      def self.included(base)
        base.alias_method_chain :link_to_remote, :degradation
      end

      def link_to_remote_with_degradation(name, options = {}, html_options = {})
        html_options[:href] = url_for(options[:url]) if !html_options.has_key?(:href)
        link_to_remote_without_degradation(name, options, html_options)
      end
    end
  end
end

ActionView::Helpers::PrototypeHelper.send(:include,
  Bezurk::ActionView::PrototypeHelperExtensions)

The modification to link_to_remote itself is dead simple: it checks for the non-existence of a :href key in the html_options parameter and sets the :href option in the html_options parameter hash to the url_for the :url value in the options parameter hash. It then calls the original link_to_remote to do what it does best.

I’ve submitted a (trivially simple) patch to Rails in my opened ticket #7904 - DRY up link_to_remote for degradable URLs. Let’s hope this makes it in so I can kill my monkey patch!

3 Comments & TrackBacks (Add yours)

The paper doll icon that precedes each comment is an idea conceived by Vanessa Tan.

Paper doll icon
choonkeat's Gravatar

Why are you still using link_to_remote and degrading yourself (pun intended ;)

Viewer:

'show', :id => post.id }, {:id => 'show_details' } %>

Controller:

def on_show_details_click
render :update do |page|
page.alert "hello!"
end
end

Posted by: choonkeat on March 26, 2007 8am

Paper doll icon
Chu Yeow's Gravatar

Oops, forgot about your plugin heh. Was trying to install as few plugins as possible though and it’s my preference to mess with views than with controllers for this little project at work I am working on at the moment.

But definitely would use KRJS at some point! Thanks!

Posted by: Chu Yeow on March 26, 2007 10am

Paper doll icon
Rhonda Starke's Gravatar

You guys should seriously consider using unobtrusive Javascript instead of littering your html code with onclick handlers.

That whole approach is awkward in the first place. Writing a helper doesn’t make it better.

Posted by: Rhonda Starke on October 24, 2007 6pm

You can subscribe to the RSS feed for comments on this post.

Post a comment

(required)

(required, but never displayed)


You can format your comments using XHTML. Your email address will not be displayed or used for nefarious purposes.

Only following tags are allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>