DRYing up link_to_remote for degradable URLs

In: Ruby on Rails|Web development

24 Mar 2007

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 Responses to DRYing up link_to_remote for degradable URLs

Avatar

choonkeat

March 26th, 2007 at 8am

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

Avatar

Chu Yeow

March 26th, 2007 at 10am

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!

Avatar

Rhonda Starke

October 24th, 2007 at 6pm

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.