Rails Observer Field

The Rails observer field is an easy way to add an ajax select menu to your site. Below is an example to get you going.

Problem

Let's say you have a list of users on your site and want to filter them by a group. In the example we will be using gym members.

View

<%= select "gym", :gym_id, Gym.find(:all).collect { |p| [p.name, p.id]}, {:selected => params[:gym]} %>
<%= observe_field "gym_gym_id", :url => { :action => :members_by_gym , 
                                          :controller => :members},
                                          :update => "member_list", 
                                          :with => "'gym='+ escape($('gym_gym_id').value)" %>
<div id="member_list">
  <% for member in @members %>
    <%= link_to member.name, member %><br/>
  <% end %>
</div>

The first thing we do is build the select form by using the Rails Select Helper. The id of the select tag is generated by rails, "gym_gym_id". We need to pass the id name as the first parameter to the observe field. The url parameter is pretty straightforward. The update parameter of the observer field designates which element will be updated. The ":with" parameter adds a parameter to the form named "gym".

Post

Parameters: {"contoller"=>"members", "action"=>"members_by_gym", "gym"=>"1", "controller"=>"members"}

The gym parameter posted here is from the observer_field tag.

Controller

def members_by_gym
  @members = Member.find_all_by_gym_id(params[:gym])
  render :layout => false
end

It's important that you add the render :layout => false or bad things will happen. We still have one more thing to do. We have our controller being hit via ajax when the select menu changes but we need to make the html that will be updated on the page. In the view/members folder we need to make a new page called members_by_gym.html.erb

members_by_gym.html.erb

<% for member in @members %>
  <%= link_to member.name, member %><br/>
<% end %>

This code will be interpreted and update the member_list element on the page. That's it. Rails Ajax magic.