天天看點

Rails Cookbook翻譯(四)

(本翻譯純粹為了學習,切勿用于商業目的,轉載請指明出處:http://blog.csdn.net/fuliangliang)

Rails Cookbook翻譯(四)

處方3.4 使用Active Record為你的資料庫建立模型

問題:

  你已經有了一個關系資料庫,你想使用Active Record來建立一個模型來表示它。(我們将使用3.1部分的cookbook_dev資料庫)

解決方案:

  首先,建立一個叫做cookbook的Rails工程:

  $ rails cookbook

在cookbook應用程式的根目錄下,使用model生成器為cookbook_dev資料庫中的每一個表建立了模型的腳手架(scaffolding)(除了連接配接表外):

  ~/cookbook$ ruby script/generate model chapter
        
      create  app/models/
        
      exists  test/unit/
        
      exists  test/fixtures/
        
      create  app/models/chapter.rb
        
   identical  test/unit/chapter_test.rb
        
   identical  test/fixtures/chapters.yml
        
~/cookbook$ ruby script/generate model recipe 
        
      exists  app/models/
        
      exists  test/unit/
        
      exists  test/fixtures/
        
      create  app/models/recipe.rb
        
   identical  test/unit/recipe_test.rb
        
   identical  test/fixtures/recipes.yml
        
~/cookbook$ ruby script/generate model tag   
        
      exists  app/models/
        
      exists  test/unit/
        
      exists  test/fixtures/
        
      create  app/models/tag.rb
        
   identical  test/unit/tag_test.rb
        
   identical  test/fixtures/tags.yml
        

接下來,在app/models目錄下的檔案裡添加一下聲名:

~/cookbook/app/models/chapter.rb:

class Chapter < ActiveRecord::Base

  has_many :recipes

ene

~/cookbook/app/models/recipe.rb:

class Recipe < ActiveRecord::Base

  belong_to :chapter

  has_and_belongs_to_many :tags

end

~/cookbook/app/models/tag.rb:

class Tag < ActiveRecord::Base

 has_and_belongs_to_many :recipes

end

讨論:

  Active Record在我們cookbook資料庫的上一層建立了一個ORM層。這個層允許Rails通過Active Record類定義的面向對象的接口來和資料庫通信。在這個映射中,類代表資料庫中的表,而對象則代表表中的行。

  我們的資料庫包含了一對多和多對多的關系。我們需要提供給Active Record一些資訊來說明他們之間是什麼關系。我們通過使用Active Record類定義的每一個模型中聲明這種關系。

   對于chaptes和recipes之間的一對多的關系,我們在chapter.rb中添加了has_many :recipes,在recipe.rb中添加了belongs_to :chapter。注意這些聲明就像使用英語那樣描述關系(例如,“Chapter have many recipes.”)。通過使用類似真實語言的方式,幫助我們使複雜的資料模型概念化。

   這個在recipes和tags之間的多對多的關系仍需要Active Record聲明的幫助。我們已經在recipes.rb裡添加了has_and_belongs_to_many :tags,在tags.rb裡添加了has_and_belongs_to_many :recipes。充當媒介的reicpes_tags連接配接表的沒有一點蹤迹。這是被設計好了的。Active Record在背後來處理和維護多對多關系的複雜性,提供通路資料的一個符合直覺得接口。

  你可以通過使用Rails控制台來驗證這些模式的存在以及它們之間的關系。在你應用程式的根目錄運作腳本script/console,讓你進入了irb會話,通過它可以通路你的Rails環境。(-s選項告訴控制台當你退出時復原所有對資料庫的改變。)

~/cookbook/test$ ruby script/console –s

Loading development environment in sandbox.

Any modifications you make will be rolled back on exit.

首先建立一個chapter對象:

>> c = Chapter.new
        
=> #<Chapter:0x8e158f4 @new_record=true, @attributes={"sort_order"=>0,
        
"title"=>nil}>
        

接着建立Recipe對象:

>> r = Recipe.new
        
=> #<Recipe:0x8e131d0 @new_record=true, @attributes={"see_also"=>nil,
        
"discussion"=>nil, "sort_order"=>0, "title"=>nil, "chapter_id"=>nil,
        
"solution"=>nil, "problem"=>nil}>
        

現在,把recipe添加到chapter裡:

>> c.recipes << r

=> [#<Recipe:0x8e131d0 @new_record=true, @attributes={"see_also"=>nil,

"discussion"=>nil, "sort_order"=>0, "title"=>nil, "chapter_id"=>nil,

"solution"=>nil, "problem"=>nil}>]

觀察一下Chapter對象,顯示我們已經成添加了我們的recipe對象了。

>> c
        
=> #<Chapter:0x8e158f4 @new_record=true, @recipes=[#<Recipe:0x8e131d0
        
@new_record=true, @attributes={"see_also"=>nil, "discussion"=>nil,
        
"sort_order"=>0, "title"=>nil, "chapter_id"=>nil, "solution"=>nil,
        
"problem"=>nil}>], @attributes={"sort_order"=>0, "title"=>nil}>
        

現在我們可以通過章節中的recipes數組來通路chapter中的每一個recipes了.

>> c.recipes

=> [#<Recipe:0x8e131d0 @new_record=true, @attributes={"see_also"=>nil,

"discussion"=>nil, "sort_order"=>0, "title"=>nil, "chapter_id"=>nil,

"solution"=>nil, "problem"=>nil}>]

記住你可以一直通過調用methods方法來檢視一個對象的所擁有方法。

>> c.methods
        

我們建立了一個Tag對象并且添加到Recipe對象中,來示範recipes到tags的關系。

>> t = Tag.new

=> #<Tag:0x8e09e3c @new_record=true, @attributes={"name"=>nil}>

>> r.tags << t

=> [#<Tag:0x8e09e3c @new_record=true, @attributes={"name"=>nil}>]

Finally, inspection confirms that the Tag was added to our Recipe object:

>> r.tags

=> [#<Tag:0x8e09e3c @new_record=true, @attributes={"name"=>nil}>]