Recipe 5.3. Creating a Sticky Select List


Problem

You've set up scaffolding for one of your models, and you want to add a select list that incorporates information about an associated model to the edit form. This select list should remember and display the value or values selected from the most recent submission of the form.

Solution

You have an application that tracks assets and their types. The following model definitions set up the relationship between assets and asset types:

app/models/asset.rb:

class Asset < ActiveRecord::Base   belongs_to :asset_type end

app/models/asset_type.rb:

class AssetType < ActiveRecord::Base   has_many :assets end

For your view, you'll need access to all asset types to display in the select list. In the controller, retrieve all AssetType objects and store them in an instance variable named @asset_types:

app/controllers/assets_controller.rb:

class AssetsController < ApplicationController   def edit     @asset = Asset.find(params[:id])     @asset_types = AssetType.find(:all)   end   def update     @asset = Asset.find(params[:id])     if @asset.update_attributes(params[:asset])       flash[:notice] = 'Asset was successfully updated.'       redirect_to :action => 'show', :id => @asset     else       render :action => 'edit'     end   end end

In the edit form, create a select tag with a name attribute that adds asset_type_id to the params hash upon form submission. Use options_from_collection_for_select to build the options of the select list from the contents of @asset_types.

app/views/assets/edit.rhtml:

<h1>Editing asset</h1> <% form_tag :action => 'update', :id => @asset do %>   <%= render :partial => 'form' %>   <p>   <select name="asset[asset_type_id]">     <%= options_from_collection_for_select @asset_types, "id", "name",                                             @asset.asset_type.id %>   </select>   </p>   <%= submit_tag 'Edit' %> <% end %> <%= link_to 'Show', :action => 'show', :id => @asset %> | <%= link_to 'Back', :action => 'list' %>

Discussion

The solution creates a select list in the asset edit view that is initialized with the previously selected asset_type. The options_from_collection_for_select method takes four parameters: a collection of objects, the string value of the select list element, the string name of the element, and the record ID of the item in the list that should be selected by default. So passing @asset.asset_type.id as the fourth parameter makes the previously selected asset type sticky.

Similar to many of the helper methods in Action View, options_from_collection_for_select is just a wrapper around a more general method, in this case, options_for_select. It's implemented internally as:

def options_from_collection_for_select(collection,                                         value_method,                                         text_method,                                         selected_value = nil)   options_for_select(     collection.inject([]) do |options, object|        options << [ object.send(text_method), object.send(value_method) ]     end,         selected_value   ) end

Make the following addition to the show view to display the current asset type:

<p>   <b>Asset Type:</b> <%=h @asset.asset_type.name %> </p>

Figure 5-3 shows the results of the solution's select list.

Figure 5-3. A sticky select list in action


See Also

  • Section 5.4"




Rails Cookbook
Rails Cookbook (Cookbooks (OReilly))
ISBN: 0596527314
EAN: 2147483647
Year: 2007
Pages: 250
Authors: Rob Orsini

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net