Contents 

Ruby on Rails: Up and Running
Table of Contents
Copyright
Preface
Chapter 1. Zero to Sixty: Introducing Rails
Section 1.1. Rails Strengths
Section 1.2. Putting Rails into Action
Section 1.3. Organization
Section 1.4. The Web Server
Section 1.5. Creating a Controller
Section 1.6. Building a View
Section 1.7. Tying the Controller to the View
Section 1.8. Under the Hood
Section 1.9. What's Next?
Chapter 2. Active Record Basics
Section 2.1. Active Record Basics
Section 2.2. Introducing Photo Share
Section 2.3. Schema Migrations
Section 2.4. Basic Active Record Classes
Section 2.5. Attributes
Section 2.6. Complex Classes
Section 2.7. Behavior
Section 2.8. Moving Forward
Chapter 3. Active Record Relationships
Section 3.1. belongs_to
Section 3.2. has_many
Section 3.3. has_one
Section 3.4. What You Haven't Seen
Section 3.5. Looking Ahead
Chapter 4. Scaffolding
Section 4.1. Using the Scaffold Method
Section 4.2. Replacing Scaffolding
Section 4.3. Generating Scaffolding Code
Section 4.4. Moving Forward
Chapter 5. Extending Views
Section 5.1. The Big Picture
Section 5.2. Seeing Real Photos
Section 5.3. View Templates
Section 5.4. Setting the Default Root
Section 5.5. Stylesheets
Section 5.6. Hierarchical Categories
Section 5.7. Styling the Slideshows
Chapter 6. Ajax
Section 6.1. How Rails Implements Ajax
Section 6.2. Playing a Slideshow
Section 6.3. Using Drag-and-Drop to Reorder Slides
Section 6.4. Drag and Drop Everything (Almost Everything)
Section 6.5. Filtering by Category
Chapter 7. Testing
Section 7.1. Background
Section 7.2. Ruby's Test::Unit
Section 7.3. Testing in Rails
Section 7.4. Wrapping Up
Appendix A. Installing Rails
Section 1.1. Windows
Section 2.1. OS X
Section 3.1. Linux
Appendix B. Quick Reference
Section 5.1. General
Section 5.2. Testing
Section 5.3. RJS (Ruby JavaScript)
Section 5.4. Active Record
Section 5.5. Controllers
Section 5.6. Views
Section 5.7. Ajax
Section 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 for all.

Prev Page Next Page
Previous Page
Next Page

3.2. has_many

We'll need to implement has_many relationships on both Photo and Slideshow. Figure 3-2 shows the mapping between Active Record objects and database tables with has_many.

Figure 3-2. The entity (slideshow) has_many associations (slides) relationship is a one-to-many relationship

has_many is the other side of a belongs_to relationship, so you don't need to modify the class or table for Slide. You can merely add the relationship has_many to slideshow.rb:

class Slideshow < ActiveRecord::Base
  has_many :slides
end

And now, photo.rb:

class Photo < ActiveRecord::Base
  has_many :slides
  validates_presence_of :filename
end

By specifying that a photo has many slides, you give users the ability to use the same photo in several different slideshows. Remember: a slide is a photo and a position in a specific slideshow. So a slide can't be reused, but a photo can.

That's all you have to do to manage the second side of the relationship. Now, you can to see all of the slides associated with a photo, and all of the slides in a slideshow. As usual, you can open the console to see the model in action:

>> slide = Slide.find 1
...
>> slideshow = slide.slideshow
...
>> slideshow.slides.each {|slide| puts slide.photo.filename}
balboa_park.jpg
camel.jpg
cat_and_candles.jpg
hut.jpg
mosaic.jpg
polar_bear.jpg
police.jpg
sleeping_dog.jpg
stairs.jpg

So you get a list of slides in the slideshow, and each has an associated photo. Active Record is now managing the has_many relationship between Slideshow and Slide. You could use photo.slides in the same way. Table 3-2 shows you the metaprogramming for has_many.

Cascading Relationships

Many-to-one relationships introduce some problems for persistence frameworks. Primarily, the framework designer has to decide whether deleting a parent object also deletes child objects as well. Automatic deletion of dependent objects is called cascading deletes. Sometimes, you want automatic deletion to happen. For example, deleting an invoice should also delete the line items for that invoice. But sometimes, you want related objects to stay: employees should not be deleted when a department is dissolved. If you define a relationship with the :dependent option, deleting a row also deletes the associated objects. For example, to define an invoice, you might specify your invoice like this:

class Invoice < ActiveRecord::Base
  has_many :line_items, dependent => true
end

With this definition, deleting an invoice would also delete associated line items, each with a separate query. Sometimes, using a separate query to delete each child is unnecessarily inefficient, but there's a remedy. If the line items belong to one invoiceand only oneyou can set the exclusively_dependent parameter on has_many to true, and Active Record will delete all dependent objects with one query.

Similarly, when you read an object, you need to decide whether to load dependent objects. By default, Active Record does not cascade loads. But you can load children when you load a parent by using the :include option on any finder.


Table 3-2. Metaprogramming for has_many

Added feature

Description

Methods

<associations><< object

Add an object to the <associations> collection:

photo.slides << a_slide

<associations>.delete object

Delete an object in the <associations> collection. The objects will be destroyed if the dependent parameter of has_many is set to TRue:

photo.slides.delete a_slide

<associations>_singular_ids collection

Replace the <associations> collection with a collection of objects identified by ids in the collection:

photo.slides_singular_ids [1, 2, 3, 4]

<associations>.find

Uses the same rules as a basic find, but operates only on the items in the <associations> collection:

photo.slides.find_by_position 4

<associations>.clear

Delete all of the objects in the association:

photo.slides.clear

<associations>.empty?

Test to see if <associations> collection is empty:

photo.slides.clear

<associations>.size

Return the number of items in the <associations> collection:

photo.slides.size

<associations>.build

Build an object of the associated type, but do not initialize it to the root object. It takes a hash map of attributes for the new object as a parameter:

slide.build_photo(:filename => "cat.jpg"

In this example, photo.slide is initialized to nil.

<associations>.create

Create an object of the associated type, initialized to the root object. It takes a hash map of attributes for the new object as a parameter:

slide.build_photo(:filename => "cat.jpg"

In this example, photo.slide is initialized to slide.

Attributes

<associations>

A collection of the associated objects:

slide.photos[4]



Previous Page
Next Page