Extend String to use ActionView's Text Helpers
programming, ruby, rubyonrails August 7th, 2006Ruby on Rails and Ruby are an amazing combo. Here's another example of why.
ActionView's TextHelper methods are useful, but I often need to use them in my controller or my model. For several of the TextHelper methods that expect a string as input, it makes sense to extend the String class.
So, if I want to strip HTML tags, auto link any URLs, and then simple format a comment (in that order) before I save it in the database I can do:
#…
def before_save
self.text = self.text.strip_tags.auto_link.simple_format
end
end
This method is much cleaner than including ActionView::Helpers::TextHelper in whatever class I'm in and passing the string as an argument to each method.
Below is the magic code. Since TextHelper is a module, we create a Singleton class to reference the methods, create the wrapper methods in their own module, and finally include that module in the String class. Note that not all TextHelper methods are included–just the ones that make sense. Drop this code into a file and require it in your environment or within a plugin.
# Let's extend the String class to allow us to call
# some of these methods directly on a String.
# Note:
# - cycle-related methods are not included
# - concat is not included
# - pluralize is not included because it is in
# ActiveSupport String extensions already
# (though they differ).
# - markdown requires BlueCloth
# - textilize methods require RedCloth
# Example:
# "<b>coolness</b>".strip_tags -> "coolness"
require 'singleton'
# Singleton to be called in wrapper module
class TextHelperSingleton
include Singleton
include ActionView::Helpers::TextHelper
include ActionView::Helpers::TagHelper #tag_options needed by auto_link
end
# Wrapper module
module MyExtensions #:nodoc:
module CoreExtensions #:nodoc:
module String #:nodoc:
module TextHelper
def auto_link(link = :all, href_options = {}, &block)
TextHelperSingleton.instance.auto_link(self, link, href_options, &block)
end
def excerpt(phrase, radius = 100, excerpt_string = "…")
TextHelperSingleton.instance.excerpt(self, phrase, radius, excerpt_string)
end
def highlight(phrase, highlighter = '<strong class="highlight">\1</strong>')
TextHelperSingleton.instance.highlight(self, phrase, highlighter)
end
begin
require_library_or_gem 'bluecloth'
def markdown
TextHelperSingleton.instance.markdown(self)
end
rescue LoadError
# do nothing. method will be undefined
end
def sanitize
TextHelperSingleton.instance.sanitize(self)
end
def simple_format
TextHelperSingleton.instance.simple_format(self)
end
def strip_tags
TextHelperSingleton.instance.strip_tags(self)
end
begin
require_library_or_gem 'redcloth'
def textilize
TextHelperSingleton.instance.textilize(self)
end
def textilize_without_paragraph
TextHelperSingleton.instance.textilize_without_paragraph(self)
end
rescue LoadError
# do nothing. methods will be undefined
end
def truncate(length = 30, truncate_string = "…")
TextHelperSingleton.instance.truncate(self, length, truncate_string)
end
def word_wrap(line_width = 80)
TextHelperSingleton.instance.word_wrap(self, line_width)
end
end
end
end
end
# extend String with the TextHelper functions
class String #:nodoc:
include MyExtensions::CoreExtensions::String::TextHelper
end
This idea and code was somewhat inspired by Gabriel's post on using helpers inside a controller. Thanks Gabriel!
August 10th, 2006 at 7:02 pm
It's always felt ugly to me to have functions taking parameters, where they feel like they should be methods instead. So your example is nice
September 29th, 2006 at 3:19 am
Superb..
October 11th, 2006 at 5:21 am
This is really very helpful.
Thanks Curt
March 29th, 2007 at 8:35 am
Thanks for your solution!
October 20th, 2007 at 11:25 am
Edge Rails has moved things around. To maintain compatibility:
class TextHelperSingleton
  …
  include ActionView::Helpers::SanitizeHelper #added
end
Till things change again.
October 25th, 2008 at 2:28 am
With Rails 2.2 there's some refactoring in Sanitize Helper. So to make it work, change the TextHelperSingleton to:
class TextHelperSingleton
include Singleton
include ActionView::Helpers::TextHelper
include ActionView::Helpers::TagHelper #tag_options needed by auto_link
include ActionView::Helpers::SanitizeHelper
extend ActionView::Helpers::SanitizeHelper::ClassMethods # Required for rails 2.2
end
Cheers, –Kip