Section 3.1. belongs_to


3.1. belongs_to

The most common database relationship is many-to-one . Figure 3-1 shows how Active Record maps the "many" side of such a relationship. In Photo Share, we want users to be able to build slideshows. A slideshow contains an ordered list of pictures. We can't simply use pictures in a slideshow because a picture has no way of keeping its position in a slideshow, so we'll introduce a Slide class. We'll then need a many-to-one relationship between slides and slideshows: a slideshow consists of many slides, but each slide (a photo combined with a position) can belong to only one slideshow. To give us the flexibility that we need (we'll also want the ability to reuse photos in different slideshows), we'll need another relationship between photos and slides, but let's leave that for later.

Figure 3-1. belongs_to :association relationship between Entity (Slide) and Association (Slideshow)

As before, let's create our database tables in a migration, so it will be easy to back out any unnecessary changes. Generate a model and migration to create a new class for Slide , and another for Slideshow :

 ruby script/generate model Slideshow     ruby script/generate model Slide 

Rails generates the models and migrations for slideshows and slides. Now, edit the new migration in db/migrate/create_slideshow.rb . As before, we'll create steps to migrate up and down. The up step will create the slides and slideshows tables, and the down step will drop them, like this:

 class CreateSlideshows < ActiveRecord::Migration   def self.up     create_table "slideshows" do t       t.column "name", :string       t.column "created_at", :datetime end   end   def self.down     drop_table "slideshows"   end end 

Edit the new migration in db/migrate/create_slide.rb , like this:

 class CreateSlides < ActiveRecord::Migration   def self.up     create_table "slides" do t       t.column "position", :integer       t.column "photo_id", :integer       t.column "slideshow_id", :integer     end   end   def self.down     drop_table "slides"   end end 

You can now run the migrations:

 rake migrate 

If you want, you can verify that you have slide and slideshow tables in your database. If you decide that adding these tables was a huge mistake, you could back up to the previous version by typing rake migrate VERSION=1 , which would run the down method in all migrations greater than 1, starting with the greatest. You can move to any version number in this way. Be careful, though: if your migration drops a table, you'll lose that data.

At this point, some data to test the new relationships would be nice. Because we're not running these in formal tests or in production, let's create some simple SQL scripts. [*] Create a script called slideshow_data.sql :

[*] You normally wouldn't need to create test data in this way. You would use text fixtures, and load the fixtures with the command rake load fixtures . See Chapter 7 for more details on using test fixtures.

 insert into slideshows values (1, 'Interesting pictures',  now(  ));     insert into slides values (1,  1, 1, 1);     insert into slides values (2,  2, 2, 1);     insert into slides values (3,  3, 3, 1);     insert into slides values (4,  4, 4, 1);     insert into slides values (5,  5, 5, 1);     insert into slides values (6,  6, 6, 1);     insert into slides values (7,  7, 7, 1);     insert into slides values (8,  8, 8, 1);     insert into slides values (9,  9, 9, 1);     insert into photos values (1,  "balboa_park.jpg");     insert into photos values (2,  "camel.jpg");     insert into photos values (3,  "cat_and_candles.jpg");     insert into photos values (4,  "hut.jpg");     insert into photos values (5,  "mosaic.jpg");     insert into photos values (6,  "polar_bear.jpg");     insert into photos values (7,  "police.jpg");     insert into photos values (8,  "sleeping_dog.jpg");     insert into photos values (9,  "stairs.jpg"); 

First, migrate down to zero and back up by typing rake migrate VERSION=0 and then rake migrate to make sure that you're starting from scratch. These commands will drop all of the tables and create them again. Start the MySQL prompt, type use photos_development , and execute the script by typing source db/slideshow_data.sql at the MySQL prompt. Now that you have working tables, you can edit the new model in app/models/slide.rb . Add the relationship between slides and slideshows to the new Slide model class:

 class Slide < ActiveRecord::Base       belongs_to :slideshow       belongs_to :photo     end 

Save your changes, and you've got a working belongs_to relationship from Slide to Slideshow and another from Slide to Photo . To see it in action, go back to the Rails console. (If you closed the console, type ruby script/console to restart it.) Type the lines in bold:

 >>  slide = Slide.find 1  => ...     >>  slide.photo.filename  => "balboa_park.jpg"     >>  slide.slideshow.name  => "Interesting pictures" 

belongs_to introduces the photo and slideshow instance variables on slide , and also some behavior. Table 3-1 shows the methods added to the model by the belongs_to method.

Table 3-1. Metaprogramming for belongs_to and has_one

Added Feature

Description

Methods

<association>.nil?

Test the association for a nil value: slide.photo.nil?

build_<association>

Build an object of the associated type. Do not initialize the built object to the root object: slide.build_photo(:filename => "cat.jpg"

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

create_<association>

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.create_photo({:filename => "cat.jpg", :name => "cat"}

Attributes

<association>

An attribute of the type of the associated object: belongs_to :photo on Slide allows slide.photo and slide.photo = nil


belongs_to is only the "many" end of a many-to-one relationship. Let's look at the "one" side.



Ruby on Rails[c] Up and Running
Ruby on Rails[c] Up and Running
ISBN: B003D3OGCY
EAN: N/A
Year: 2006
Pages: 94

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