 |
Using Selection Lists in Rails
Posted by bleonard on July 10, 2007 at 07:17 AM | Comments (0)
Selection lists (drop down boxes) are common to just about every web application. In this entry I extend the web log I've been building to include a category selection list.
Setting Things Up
I'm going to begin from where I left off in my previous post: An Introduction to Using AJAX with Rails. Alternatively, you can start from BlogDemoAJAX.zip, which is the completed project from that post.
Test the BlogDemo Project
- Open the BlogDemo project.
- Note, if you are starting with the provided BlogDemo project, you will also need to create the BlogDemo_development database and run the migrations.
- Run the project and browse to http://localhost:3000/blog to verify that it works.
The Plan
We're going to add the ability to assign our blog entries a category. We're going to do this by providing a list of categories to choose from when the entry is created. The list of available categories will be retrieved from a database table.
Step 1: Create the Categories Model
- Generate a new model named Category.
- Open CreateCategories and add the following to the self.up method which will create the categories table with the category string, create a category reference in the posts table (which will be required), and for good measure, define the foreign key relationship. Oh yeah, we also insert some test data.
def self.up
create_table :categories do |t|
t.column 'category', :string
end
add_column 'posts', 'category_id', :integer, {:null => false}
execute "alter table posts add constraint fk_post_categories " <<
"foreign key (category_id) references categories(id)"
Category.create(:category => 'Java')
Category.create(:category => 'Ruby')
Category.create(:category => 'JavaScript')
Category.create(:category => 'NetBeans')
Category.create(:category => 'Personal')
end
- For completeness, add the following to the self.down method:
def self.down
execute "alter table posts drop foreign key fk_post_categories"
remove_column 'posts', 'category_id'
drop_table :categories
end
- Right-click the project and select Migrate Database > To Current Version:

- If you try to create a new blog entry now, it will fail because category_id can't be null:
Add the Category Select List
- Alt+Shift+O to open the _form.rhtml partial.
- Here we'll use the select helper to create our drop down box. Above the post title in _form.rhtml, add the following:
<!--[form:post]--> <p><label for="post_category">Category</label><br/> <%= select 'post', 'category_id', Category.find(:all).collect {|c| [c.category, c.id]}, :prompt => "Select a Category" %>
'post' and 'category_id' map to the post model just like the title and body fields. The 3rd parameter:
Category.find(:all).collect {|c| [c.category, c.id]},
returns a collection of all the categories (for display to the user) and their associated ids (for storage in the post tables category_id field). The final parameter:
:prompt => "Select a Category" %>
Just set's prompt instructing the user to select a category.
- Now we should be able to create an entry if we select a category:
- But if you fail to select a category, we get the same 'category_id' cannot be null error.
Validate Presence
- Alt+Shift+O to open Post.
- Type vp+tab to insert the validates_presence_of template and set the :attribute to :category_id
validates_presence_of :category_id
- Save and try to insert the post again without a category selected:

Display the Selected Category
As a final step we're going to update the show page to display the post's category.
- Alt+Shift+0 to open show.rhtml.
- Replace the for loop at the top of the file with the following:
<p><b>Category:</b> <%= @post.category.category %></p> <p><b>Title:</b> <%= @post.title %></p> <p><b>Body:</b> <%= @post.body %></p>
- Save and browse to the show page:
Although we set up the foreign key relationship between posts and categories in our database, Rails knows nothing about it.
- Switch to post.rb and add the following:
belongs_to :category
And try again:
The Completed Application
BlogDemoCategory.zip
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
|