(本翻譯純粹為了學習,切勿用于商業目的,轉載請指明出處: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}>]