4

I'm creating an app using twitter bootstrap. I'm using Font Awesome to add icons to various places, very often links. So far I've been using a global helper. Here's the simplified version:

# app/helpers/link_to_with_icon.rb
def link_to_with_icon(text, path, options={})
  options = options.clone
  icon = options.delete(:icon)
  text = "<i class='#{icon}'></i> #{text}" if icon.present?
  link_to(text, path, options)
end

This worked, but I had to remember changing link_to to link_to_with_icon every time I needed to add an icon to a new link (the app is new, so that's kindof in constant flux). So I decided to stop using link_to completely, and replaced it with link_to_with_icon (since it is compatible).

But then I realized that since I'm not using link_to any more, I might as well modify link_to in the first place. Surely I could add some monkeypatching on the lib folder to make it understand the :icon option.

# lib/extensions/url_helper_extensions.rb
module ActionView
  module Helpers
    module UrlHelper

      # do some magic here

    end
  end
end

I've done things similar to this before, a couple years ago. In that time alias_method_chain helper was the right tool for the job. In rails 3.x it seems to be deprecated in favor of modules and inheritance.

But if I'm understanding the examples in that page correctly, I would need the link_to method to be provided by some kind of Base module - otherwise you can't add a "Pre-Extension" to it.

Hence my question: Can I extend link_to using modules? Or must I use alias_method_chain?

In particular, a working implementation of the :icon option would be greatly appreciated.

Community
  • 1
  • 1
kikito
  • 51,734
  • 32
  • 149
  • 189

2 Answers2

3

I'd simply do:

# app/helpers/my_helper.rb

module MyHelper
  def link_to(text, path, options={})
    options = options.clone
    icon = options.delete(:icon)
    text = "<i class='#{icon}'></i> #{text}" if icon.present?
    super(text, path, options)
  end
end

But watch out if ever you use link_to with block.

kikito
  • 51,734
  • 32
  • 149
  • 189
apneadiving
  • 114,565
  • 26
  • 219
  • 213
3

I would either add this in a separate helper, or add it into ApplicationHelper

def link_to(text, path, options = {}, &block)
  icon = options.delete(:icon)
  text = content_tag(:i, text, :class => icon) if icon
  super
end

And you don't want to clone the options Hash because you don't want the icon option to be sent to the original link_to method.

Lee Jarvis
  • 16,031
  • 4
  • 38
  • 40
  • Good point about just using a helper. Thanks. Regarding cloning: Take a closer look. The `:icon` option is not being sent to `link_to`. But I don't want to modify `options` directly since it might be used in several links (delete is a destructive method, it modifies the hash). – kikito Nov 26 '12 at 13:54
  • Ah alright that makes sense. Then just the same code as above but with your original cloning should do the trick. – Lee Jarvis Nov 26 '12 at 13:56