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!