Recipe 3.5. Inspecting Model Relationships from the Rails Console


Problem

You want to inspect the relationships between the objects in your model to confirm you have them set up correctly. You could do this by dummying up a web application, but you want something quick and simple, and nothing beats the command line.

Solution

Use the Rails console to create objects of your models and to explore their relationships with one another.

From your project root, type:

~/projects$ ruby script/console -s Loading development environment in sandbox. Any modifications you make will be rolled back on exit.

If you're using Windows, use:

C:\myApp>ruby script/console -s             

You are then put into an irb session with full access to your project environment and its Active Record models. You can enter Ruby code, just as you would in a controller, to find any problems with your data model.

Discussion

As a demonstration, create a database for a project that tracks assets and their types. This example also associates assets with tags. Create this database by generating three models using script/generate: asset, asset_type, and tag. (Note that you don't want a model for the assets_tags association table because Rails handles it internally.)

~/project$ ruby script/generate model asset ... ~/project$ ruby script/generate model asset_type  ... ~/project$ ruby script/generate model tag ...

Now, define the specific table definitions with the following migration:

class BuildDb < ActiveRecord::Migration   def self.up     create_table :asset_types do |t|       t.column :name,          :string     end     create_table :assets do |t|       t.column :asset_type_id, :integer       t.column :name,          :string       t.column :description,   :text     end     create_table :tags do |t|       t.column :name,          :string     end     create_table :assets_tags do |t|       t.column :asset_id,      :integer       t.column :tag_id,        :integer     end   end   def self.down     drop_table :assets_tags     drop_table :assets     drop_table :asset_types     drop_table :tags   end end

Next, you can populate the database with some dummy data. Use the following SQL insert statements for this:

insert into asset_types values (1,'Photo'); insert into asset_types values (2,'Painting'); insert into asset_types values (3,'Print'); insert into asset_types values (4,'Drawing'); insert into asset_types values (5,'Movie'); insert into asset_types values (6,'CD'); insert into assets values (1,1,'Cypress','A photo of a tree.'); insert into assets values (2,5,'Blunder','An action film.'); insert into assets values (3,6,'Snap','A recording of a fire.'); insert into tags values (1,'hot'); insert into tags values (2,'red'); insert into tags values (3,'boring'); insert into tags values (4,'tree'); insert into tags values (5,'organic'); insert into assets_tags values (1,4); insert into assets_tags values (1,5); insert into assets_tags values (2,3); insert into assets_tags values (3,1); insert into assets_tags values (3,2);

Now set up the relationships between the models. This example includes a one-to-many and a many-to-many relationship.

asset_type.rb:

class AssetType < ActiveRecord::Base   has_many :assets end

tag.rb:

class Tag < ActiveRecord::Base   has_and_belongs_to_many :assets end

asset.rb:

class Asset < ActiveRecord::Base   belongs_to :asset_type   has_and_belongs_to_many :tags end

Now that we've got the model set up and have some data loaded, we can open a console session and have a look around:

~/project$ ruby script/console -s Loading development environment in sandbox. Any modifications you make will be rolled back on exit. >> a = Asset.find(3) => #<Asset:0x4093fba8 @attributes={"name"=>8220;Snap", "id"=>"3", "asset_type_id"=>"6", "description"=>"A recording of a fire."}> >> a.name   => "Snap"  >> a.description => "A recording of a fire."  >> a.asset_type  => #<AssetType:0x4093a090 @attributes={"name"=>"CD", "id"=>"6"}> >> a.asset_type.name => "CD"  >> a.tags => [#<Tag:0x40935acc @attributes={"name"=>"hot", "tag_id"=>"1", "id"=>"1", "asset_id"=>"3"}>, #<Tag:0x40935a90 @attributes={"name"=>"red", "tag_id"=>"2", "id"=>"2", "asset_id"=>"3"}>] >> a.tags.each { |t| puts t.name } hot red => [#<Tag:0x40935acc @attributes={"name"=>"hot", "tag_id"=>"1", "id"=>"1", "asset_id"=>"3"}>, #<Tag:0x40935a90 @attributes={"name"=>"red", "tag_id"=>"2", "id"=>"2", "asset_id"=>"3"}>]

In the console session, we retrieve the asset record with an ID of 3 and store it in an object. We display the asset's name and description. Fetching the asset's type returns an AssetType object. The next line returns the name of that asset type.

Accessing the tags of this asset object returns an array consisting of the asset's tags. The next command iterates over these tags and prints each tag name.

As objects become larger and more complex, their printed representation in the console can become quite difficult to read. Printing model objects to the console with pp (pretty-print) or y (yaml) can greatly improve the readability of the information. Try the following commands in the console:

require 'pp' asset = Asset.find(:first) pp asset y asset

The y method prints the object in YAML format and is really just a shortcut for:

                puts asset.to_yaml             

Examining your model in this stripped-down environment is a great way to make sure that there are no problems. Doing similar testing within the controllers of your application

could make an obvious

problem a little harder to find.

See Also

  • Section 10.1"




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