Contents 

Ruby on Rails:
Table of Contents
Preface
Zero to Sixty: Introducing Rails
1.1. Rails Strengths
1.2. Putting Rails into Action
1.3. Organization
1.4. The Web Server
1.5. Creating a Controller
1.6. Building a View
1.7. Tying the Controller to the View
1.8. Under the Hood
1.9. What's Next?
Active Record Basics
2.1. Active Record Basics
2.2. Introducing Photo Share
2.3. Schema Migrations
2.4. Basic Active Record Classes
2.5. Attributes
2.6. Complex Classes
2.7. Behavior
2.8. Moving Forward
Active Record Relationships
3.1. belongs_to
3.2. has_many
3.3. has_one
3.4. What You Haven't Seen
3.5. Looking Ahead
Scaffolding
4.1. Using the Scaffold Method
4.2. Replacing Scaffolding
4.3. Generating Scaffolding Code
4.4. Moving Forward
Extending Views
5.1. The Big Picture
5.2. Seeing Real Photos
5.3. View Templates
5.4. Setting the Default Root
5.5. Stylesheets
5.6. Hierarchical Categories
5.7. Styling the Slideshows
Ajax
6.1. How Rails Implements Ajax
6.2. Playing a Slideshow
6.3. Using Drag-and-Drop to Reorder Slides
6.4. Drag and Drop Everything (Almost Everything)
6.5. Filtering by Category
Testing
7.1. Background
7.2. Ruby's Test::Unit
7.3. Testing in Rails
7.4. Wrapping Up
Installing Rails
1.1. Windows
2.1. OS X
3.1. Linux
Quick Reference
5.1. General
5.2. Testing
5.3. RJS (Ruby JavaScript)
5.4. Active Record
5.5. Controllers
5.6. Views
5.7. Ajax
5.8. Configuring Your Application
About the Authors
Colophon
Index
A
B
C
D
E
F
G
H
I
J
L
M
N
O
P
R
S
T
U
V
W
X
Y
Z

Ruby on Rails manual

Prev Page Next Page
Previous Page
Next Page

6.5. Filtering by Category

Displaying all unused photos might seem acceptable right now, but we have only nine photos. If there were 900, it would quickly become unusable. So, our final feature in this chapter will be to display only the unused photos in a particular category.

The first thing to do in our controller is get a list of all categories that can populate the drop-down selection box. Edit photos/app/controllers/slideshows_controller.rb, and add this line to the end of the edit method:

@all_categories = Category.find(:all, :order=>"name")

This line retrieves a list of categories that can populate a drop-down selection box that the user will use to display only those unused photos that are in the selected category.

Now, edit photos/app/views/slideshows/edit.rhtml, and add this right after the 'Play this Slideshow' line:

<p>
  <label for="category_id">Filter "Unused Photos" on this Category</label><br/>
  <%= collection_select(:category, :id, @all_categories, :id, :long_name) %>
  <%= observe_field(:category_id,
               :frequency => 2.0,
               :update => 'slideshow-photos',
               :url => { :action => 'change_filter'},
               :with => 'category_id' ) %>
</p>

The collection_select helper is normally used inside an HTML form, but here we are using it because it conveniently knows how to display a collection in a drop-down box. It will never be submitted as part of a form.

As shown, the observe_field helper checks the category drop-down box for changes every two seconds. When a change is detected, an Ajax request is fired off to the change_filter method, which returns new HTML (that has been appropriately filtered) to replace the slideshow-photos .

The Category model class automatically shows a collection of all photos that are in a particular category. However, we need to get a collection of photos that are in a given category and in all of its child categories.

Edit photos/app/models/category.rb, and add this method:

def photos_including_child_categories
  result = photos.clone
  children.each do |c|
    c.photos_including_child_categories.each {|p|
      result << p if not result.include? p}
  end
  result
end

This method recursively collects a list of all photos in its own category and all of its child categories. You can use this in to get the list of unused photos to display.

In the meantime, edit photos/app/controllers/slideshows_controller.rb to add the change_filter method:

  def change_filter
    slideshow_id = session[:slideshow].id
    category_id = params[:category_id] || 1
    session[:category_id] = category_id
    @slideshow = Slideshow.find(slideshow_id)
    session[:slideshow] = @slideshow
    @photos = unused_photos(@slideshow)
    render_partial 'photo_picker'
  end

This method stores the chosen category id in the session hash, retrieves a new list of unused photos, and then renders the photo_picker. Notice the bold code line in the previous code. This line tries to retrieve the category id from the request parameters. If there aren't any parameters, params[:category_id] returns nil, and the || operator returns the rightmost argument ("1" in this case).

Also, in this slideshow controller, we need to update the method that retrieves the unused photos to pay attention to the category setting. Do so by editing the unused_photos method; then replace the line all_photos = Photo.find(:all) with the following:

category_id = session[:category_id] || 1
session[:category_id] = category_id
category = Category.find(category_id)
all_photos = category.photos_including_child_categories

We're done; we've added category filtering! Fire up your browser, and try it (you may need to assign some categories to some unused photos). Now it looks like "#rubyrails-chp-6-fig-7">Figure 6-7.

Figure 6-7. Filtering on categories

We've come a long way in a very short time. With fewer than 200 lines of code, we've added drag-and-drop capability to add and reorder slides. We've also added the core capability to actually show a slideshow. Ajax made our application much easier to use and more attractive. Next, we'll look into testing this application.


Previous Page
Next Page