Displaying a subset of items from an association
As of this post I have two classes joined by have_and_belongs_to_many (habtm), and I figured that I’d like to be able to click on an entry in one and have a subset index of the other appear. Not an uncommon task and used by tags and blogs everywhere. Rather than search for a snippet, I thought I’d give it a go myself first.What I came up with surprised me with it’s simplicity and may not be the most expedient manner, but seems to be a neat and easy extension of the index method.
The obvious way was to add an entry to the list of actions which can be applied to a tag item. A simple addition of a “Show Users” link pointing to the Users controller and passing a tag_id parameter was the starting point for this.
Opening up app/views/tags/index.rhtml, we can add a user_path with :tag_id=>tag as the parameter. This will translate to http://localhost:3000/users?tag_id=x.
<h1>Listing tags</h1>
<table>
<tr>
<th>Name</th>
</tr>
<% for tag in @tags %>
<tr>
<td><%=h tag.name %></td>
<td><%= link_to 'Users', user_path(:tag_id=>tag) %></td>
<td><%= link_to 'Show', tag_path(tag) %></td>
<td><%= link_to 'Edit', edit_tag_path(tag) %></td>
<td><%= link_to 'Destroy', tag_path(tag), :confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New tag', new_tag_path %>
This will then allow the following in the index view of the users controller.
# GET /users
# GET /users.xml
def index
@tag=Tag.find(params[:tag_id]) if params[:tag_id]
@users = @tag.users || throw rescue User.find(:all)
respond_to do |format|
format.html # index.rhtml
format.xml { render : xml => @users.to_xml }
end
end
Note the unusual throw rescue construct. Since @tag.users would throw an exception, as well as having a nil possibility, this is the dryest form of getting the original User.find(:all) executed on error. I mainly wanted to see if this would work, and it does! I’m really starting to like what you can do with Ruby.
Trackbacks
Use this link to trackback from your own site.
Comments
You must be logged in to leave a response.