Span Tags for error_message_on in Ruby on Rails
by Jarrett Colby
We'll be implementing this as a plugin. Since we only want to change a <div>s to a <span>, we could probably get away with using alias_method_chain. But that would involve modifying the output with some regex trickery. That approach always makes me nervous—if in some cases the output is slightly different from what I expected, the regex will crash and burn.
So instead, we'll just rewrite the method. Don't worry, it's quite short. Here's the code:
module SpanErrorMessages def self.included(base) ActionView::Base.field_error_proc = Proc.new do |html_tag, instance| %(<span class="fieldWithErrors">#{html_tag}</span>) end end # Old method signature: # def error_message_on(object, method, prepend_text = "", # append_text = "", css_class = "formError"} # Use the new method like this: # error_message_on( # @employee, # :email, # :css_class => 'really_bad_error', # :tag => 'p' # ) def error_message_on(object, method, *args) options = {:tag => 'span'}.merge(args.extract_options!.symbolize_keys) prepend_text = args[0] || options[:prepend_text] || append_text = args[1] || options[:append_text] || css_class = args[2] || options[:css_class] || 'formError' if ( obj = (object.respond_to?(:errors) ? object : instance_variable_get("@#{object}")) ) && (errors = obj.errors.on(method)) content_tag(options[:tag], "#{prepend_text}#{errors.is_a?(Array) ? errors.first : errors}#{append_text}", :class => css_class) else '' end end end
Notice that we've changed the method signature. It now supports a variable number of arguments, allowing for future expansion and a final options hash. Plus it's backwards-compatible. By the way, if you haven't read about Array#extract_options!, you should. It's handy for when you have an *args parameter that can take one or more hashes at the end.
Anyhow, the options hash accepts four keys: :prepend_text, :append_text, :css_class, and :tag. Three of those used to be the optional parameters, and you can still use them that way, but I like having the choice to put them in a hash instead. It permits you to specify the css_class without filling in the default values for prepend_text and append_text.
If you're experienced with Rails plugins, you can probably figure out what to do from here. If not, you should read The Complete Guide to Rails Plugins: Part I by Geoffrey Grosenbach. Then, when you're ready to make your plugin, paste the above code into the following file:
vendor/plugins/span_error_messages/lib/span_error_messages.rb
Now create another file at:
vendor/plugins/span_error_messages/init.rb
Paste this into it:
ActionView::Base.send :include, SpanErrorMessages
Don't forget to restart your server (even if you're in development mode).