Customized page.* methods for Rails’ RJS Templates

So you want to clear your live search fields the moment someone clicks on a result. Here’s a little bit of code that will let you do so in your RJS template:

page.replace_html 'search_results', '' page[:live_search_bar].value = '' </filter:jsode>  However, suppose you want to use this same live search clearing scheme over multiple controllers. You can either do re-use the above code for each respective controller method, or you can write the following in your RJS views, thereby DRY-ing up your code:  <pre name="code" class="ruby"> page.clear_my_live_search

How, oh how ever do I implement this for my app? Well, this works because in Ruby, it’s quite easy to add or override methods to any class or module. So let’s hack into ActionView, which is the part of Rails that gives you all those neat-o functions in your views (for example: the much-loved link_to).

The trick to overriding Rails code is to always have a copy of Edge Rails checked out to refer to, so you can get the namespace right. For this example, we have established that we want to extend the page.* methods that are prevalent through RJS templates and “render :update” calls. First we need to find out where the code lives. Let’s run a text search on our edge rails copy for ‘insert_html’, which is a commonly used RJS method. We then find out that it’s at action_pack/lib/action_view/helpers/prototype_helper.rb. Well, this is a start!

Next, we look at the namespace of the code in prototype_helper.rb_, and try to find inserthtml. We then see that it’s nested like so:

module ActionView   module Helpers     module PrototypeHelper       class JavascriptGenerator         module GeneratorMethods            def insert_html               # .... code ...            end          end       end    end end

Now, in lib/actionview_hacks.rb, copy this namespace and replace the insert_html method with a method of your choice:

module ActionView   module Helpers     module PrototypeHelper       class JavascriptGenerator         module GeneratorMethods                        def clear_my_live_search               page.replace_html 'search_results', ''               page[:live_search_bar].value = ''            end           end       end    end end

Next, update your environment.rb file by adding this somewhere:

require ‘actionview_hacks’

That’s it! You can now call page.clear_my_live_search from any RJS template or render :update method. You can also use update_page_tag to insert the page. methods we just generated into your views as javascript.

Also, this example is quite basic. Some might call it overkill to override Rails helpers to get this running. Another good way of doing the same is to define a new method in one of your helpers that uses update_page, like so:

module LiveSearchHelper   def clear_my_live_search     update_page do |page|       page.replace_html 'search_results', ''       page[:live_search_bar].value = ''     end   end end

You can then use this helper all over the place, too.

This article barely touches the surface of what’s possible when extending Rails — most existing Rails plugins probably got their start by practically the same process as what we followed here.