1. 程式人生 > >Rails Cookbook翻譯(四)

Rails Cookbook翻譯(四)

Rails Cookbook翻譯(四)

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

問題:

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

解決方案:

首先,建立一個叫做cookbookRails工程:

$ rails cookbook

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

~/cookbook$ ruby script/generate model chapter
createapp/models/
existstest/unit/
existstest/fixtures/
createapp/models/chapter.rb
identicaltest/unit/chapter_test.rb
identicaltest/fixtures/chapters.yml
~/cookbook$ ruby script/generate model recipe 
existsapp/models/
existstest/unit/
existstest/fixtures/
createapp/models/recipe.rb
identicaltest/unit/recipe_test.rb
identicaltest/fixtures/recipes.yml
~/cookbook$ ruby script/generate model tag
existsapp/models/
existstest/unit/
existstest/fixtures/
createapp/models/tag.rb
identicaltest/unit/tag_test.rb
identicaltest/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類定義的每一個模型中宣告這種關係。

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

這個在recipestags之間的多對多的關係仍需要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物件中,來演示recipestags的關係。

>> 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}>]