Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Override rails helpers with access to original

Tags:

I want to use rails' familiar helpers, but with slightly altered functionality. The way I see it, I want to be able to do something like:

module AwesomeHelper   #... create alias of stylesheet_link_tag to old_stylesheet_link_tag   def stylesheet_link_tag(*args)     if @be_awesome       awesome_stylesheet_link_tag *args     else       old_stylesheet_link_tag *args     end   end end 

The way I see it, I have three options:

  1. Monkey patching: Reopening the rails helper module. If the rails team ever change the name of their helper module, my code becomes a source of brittleness. Not insurmountable, but not ideal.
  2. Use different method names: Trying to stick to the common rails interface may be my downfall. My changes may become a source of confusion for other developers
  3. Detaching methods (new): Not sure whether this would work, or whether it would have the same drawbacks as 1. Will research this, but this might be a good starting point.

So the question here is, am I stuck with one of these sub-optimal solutions, or is there another way that I haven't considered? If I go for option 3, is there a way to do it without directly addressing the rails helper module?

(Note: I have removed the context, as it adds nothing to the question.)

like image 765
user208769 Avatar asked May 06 '12 15:05

user208769


2 Answers

There's a better way than any of your listed options. Just use super:

module AwesomeHelper   def stylesheet_link_tag(*sources)     if @be_awesome       awesome_stylesheet_link_tag *sources     else       super     end   end end 

Overriding stylesheet_link_tag in AwesomeHelper will ensure that, when stylesheet_link_tag gets invoked, Ruby will encounter it in the method lookup path before it hits ActionView::Helpers::AssetTagHelper. If @be_awesome is true, you get to take charge and stop things right there, and if not, the call to super without parentheses will transparently pass through all the arguments up to the Rails implementation. This way you don't have to worry about the Rails core team moving things around on you!

like image 106
Cade Avatar answered Jan 01 '23 12:01

Cade


I don't use this gem, so I'll answer you in a more generic way.

Let's say you want to log calls to link_to helper (yeah, contrived example, but shows the idea). Looking in API gives you understanding that link_to located inside the ActionView::Helpers::UrlHelper module. So, you create some file in your, say, config/initializers directory with the following contents:

# like in config/initializers/link_to_log.rb module ActionView::Helpers::UrlHelper      def link_to_with_log(*args, &block)         logger.info '**** LINK_TO CALL ***'         link_to_without_log(*args, &block) # calling the original helper     end      alias_method_chain :link_to, :log end 

The core of this functionality -- alias_method_chain (clickable). Use it AFTER defining the method xxx_with_feature.

like image 37
jdoe Avatar answered Jan 01 '23 12:01

jdoe