程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Ruby on rails開發從頭來(五十五)- ActiveRecord基礎(一對一關聯關系)

Ruby on rails開發從頭來(五十五)- ActiveRecord基礎(一對一關聯關系)

編輯:關於JAVA

一對一關聯,或者更正確的說是一對零或一對一關聯,是通過外鍵引用到另外一張表中的至多一條記錄實現的,下圖描述了orders表和invoices表的關系:

在Active Record中,要表示這樣的關系需要在Order類中添加has_one:Invoice聲明,並且同時在Invoice類中添加聲明belongs_to:order,事實上,我們可以把這種關聯關系看作是相互的,我們可以使Invoice有一個Order,也可以使Order有一個Invoice,不同的是,在將對象存儲到數據庫時,如果我們給一個對象賦予has_one關聯給另一個既存對象,關聯的對象將會自動被保存。例如:

an_invoice = Invoice.new(...)
order.invoice = an_invoice # invoice gets saved

如果我們給一個對象賦予belongs_to關聯到另一個對象,那麼它將不會自動被保存,例如:

order = Order.new(...)
an_invoice.order = order # Order will not be saved

還有另外一個不同點,當你給一個對象賦予has_one關聯時,如果指向一個既存的子對象,這個既存對象的外鍵關聯將會被移除,也就是清零,如下圖:

還有一個危險的地方,如果子記錄不能被保存(沒有通過驗證等),Active Record也不會有抱怨,你也不會得到任何信息來指示該記錄沒有添加到數據庫,所以,我們強烈推薦使用下面的方法:

invoice = Invoice.new
# fill in the invoice
unless invoice.save!
an_order.invoice = invoice

因為save!方法在失敗的時候會拋出異常,這樣我們就知道發生了什麼。

belongs_to聲明

belongs_to聲明給一個類指定父關聯,Active Record約定在這個表中包含有引用到另一個表的外鍵,父類的名字假定為混合大小寫,且單數,外鍵字段為單數,並且在末尾添加_id,所以,下面的代碼:

class LineItem < ActiveRecord::Base
belongs_to :product
belongs_to :invoice_item
end

Active Record關聯line item到類Product和InvoiceItem,在底層,使用外鍵product_id和invoice_item_id關聯到products和invoice_items表的id列。也可以像下面這樣,給belongs_to一個哈希(hash):

class LineItem < ActiveRecord::Base
belongs_to :paid_order,
:class_name => "Order",
:foreign_key => "order_id",
:conditions => "paid_on is not null"
end

在上面的代碼裡,我們創建了一個關聯,叫做paid_order,引用了Order類,通過order_id關聯,並且paid_on字段不為null,在這種情況下,我們的關聯不直接映射到line_items表的單一的列。belongs_to()方法創建了一組實例方法來管理關聯,方法名都以關聯的名字開頭,例如:

item = LineItem.find(2)
# item.product is the associated Product object
puts "Current product is #{item.product.id}"     
puts item.product.title
item.product = Product.new(:title => "Advanced Rails",
:description => "...",
:image_url => "http://....jpg",
:price => 34.95,
:date_available => Time.now)
item.save!
puts "New product is #{item.product.id}"
puts item.product.title

運行後我們會得到下面的輸出:

Current product is 2
Programming Ruby
New product is 37
Advanced Rails

我們使用了在LineItem類中生成的方法product()和product=(),來訪問和更新關聯到line item對象上的product對象。在背後,Active Record保存數據庫的步調一致,在我們保存line item對象的時候自動保存關聯的product對象,並且將具有新的id的product對象和line item對象關聯起來。

在這種情況下,下面的方法將被生成到line item對象中:

product(force_reload=false):

返回關聯的product(如果沒有關聯的對象就返回nil),同時,結果將被緩存,對於相同的查詢,將不會到數據庫再次執行,除非force_reload參數為true。

  product=(obj)

將指定的對象關聯到line item,設置line item對象的外鍵到product對象的主鍵,如果product對象還沒有保存,那麼會在line item對象保存的同時,對product對象進行保存。

  build_product(attributes={})

使用指定的attribute,構建一個新的product對象,line item對象將鏈接到該對象,而且,該對象還沒有保存。

  Create_product(attributes={})

和上面的build_product方法基本相同,差別在於product對象會被保存。

has_one聲明

has_one聲明指定一個類為聲明所在類的子類(這裡的子類不是繼承的概念,而是與數據庫結構相對應的主從關系),has_one定義了一組和belongs_to相同的方法,所以下面的代碼:

class Order < ActiveRecord::Base
has_one :invoice
end

我們可以這樣:

order = Order.new
invoice = Invoice.new
if invoice.save
order.invoice = invoice
end

我們也可以通過傳遞一組參數來改變Active Record的默認行為,例如::class_name,:foreign_key和:conditions,就和前面介紹belongs_to時的一樣,也可以使用:dependent和:order。

:dependent的含義是,在從表中的記錄不能獨立於主表中的記錄而存在,也就是說,如果你刪除了父記錄,而且你定義了:dependent= true,Active Record將自動刪除從表中關聯的記錄。

:order指定了在記錄被返回前,怎樣進行排序,我們會在後面關於has_many的內容裡詳細討論。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved