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

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

編輯:關於JAVA

一對多關聯可以使我們表示一組對象,例如,一個order可以包含有任意多個line item,在數據庫中,所有的line item記錄都通過外鍵關聯到特定的order。

在Active Record中,通過在父對象中的has_many來定義到子對象的關聯,在子對象中使用belongs_to來指定父對象。我們已經在上一篇中了解了belongs_to聲明,實際上,在一對多的情況下,和一對一是相同的,所以我們來了解has_many聲明。

has_many聲明

has_many聲明了一個屬性,其行為就像一組子對象,可以把它看作數組來訪問,查詢特定的對象,或者添加新對象。例如:

order = Order.new
params[:products_to_buy].each do |prd_id, qty|
product = Product.find(prd_id)
order.line_items << LineItem.new(:product => product,
:quantity => qty)
end

追加操作符(>>)所作的不僅僅是向order的line_items列表中追加一個對象,並且和設置了line_item對象外鍵值為order對象主鍵值,而且在order對象保存的時候,會同時保存line_item對象。

我們可以像對數組一樣對has_many關聯進行循環:

order = Order.find(123)
total = 0.0
order.line_items.each do |li|
total += li.quantity * li.unit_price
end

和has_one一樣,我們可以改變Active Record的默認形式,我們可以給has_many一組設定,:class_name,:foreign_key,:conditions,:order和:dependent和has_one中的是一樣的,has_many還有:exclusively_dependent,:finder_sql,:counter_sql。

has_one和has_many都支持:dependent,這告訴Rails在刪除主表中記錄的同時刪除從表中對應的記錄。也就是對所有外鍵為刪除的主記錄的id的子對象調用它們destory方法。

無論如何,如果從表僅僅和主表關聯,而沒有其他表關聯,而且沒有任何鉤子方法在刪除的時候執行操作,你可以使用:exclusively_dependent來代替:dependent,在這種情況下,對於所有的子記錄會使用一條sql語句來刪除,這樣執行速度會快一點。

你還可以通過使用:finder_sql和:counter_sql設定來復寫Active Record用來對子記錄進行查詢和計數的sql。在:conditions設定不足夠的情況下,這兩個設定就很有用了。例如:

class Order < ActiveRecord::Base
has_many :rails_line_items,
:class_name => "LineItem",
:finder_sql => "select l.* from line_items l, products p " +
" where l.product_id = p.id " +
" and p.title like '%rails%'"
end

:counter_sql設定用來復寫Active Record用作計算行數的sql,如果:finder_sql被指定了,但是:counter_sql沒有指定,Active Record將會根據查詢sql來替換計算行數的sql。

:order設定指定了從數據庫中選出的記錄的排序所使用的sql,如果你在遍歷記錄集的時候需要有特定的排序,你就需要指定:order,也就是設定sql語句的order by部分,默認情況下,所有的字段都是升序。例如:

class Order < ActiveRecord::Base
has_many :line_items,
:order => "quantity, unit_price DESC"
end

現在再回到has_one聲明,我們前面提到過也支持:order,但是一條父記錄最多只有一條子記錄,那麼為什麼要支持:order來允許指定排序條件呢?想象一下這樣的場景,一個用戶可能有多條訂單,但是,如果我們想查看該用戶的最新一條訂單呢?這時候,我們就可以使用has_one聲明了:

class Customer < ActiveRecord::Base
has_many :orders
has_one :most_recent_order,
:class_name => 'Order',
:order => 'created_at DESC'
end

上面的代碼創建了一個新屬性:most_recent_order,將會引用到該用戶的最新一條訂單,我們可以這樣使用它:

cust = Customer.find_by_name("Dave Thomas")
puts "Dave last ordered on #{cust.most_recent_order.created_at}"

實際上,Active Record執行了下面的sql:

SELECT * FROM orders
WHERE customer_id = ?
ORDER BY created_at DESC
LIMIT 1

根據前面我們學習的find方法,可以看到只取了排序後的第一條記錄。

has_many添加的方法

就像belongs_to和has_one,has_many也添加了一組屬性相關的方法在它所在的類中,下面我們來看看這些方法,我們的聲明是這樣

class Customer < ActiveRecord::Base
has_many :orders
end

l     orders(force_reload=false)=

返回一個和用戶關聯的訂單的數組,結果集是被緩存的,對於相同的查詢,不會再次從數據庫提取數據,除非force_reload = true。

l     orders <<order

添加訂單到指定用戶的訂單的列表中。

l     orders.push(order1, ...)

添加一個或多個訂單對象到用戶的訂單列表中,concat()是該方法的別名。

l     orders.delete(order1, ...)

從用戶的訂單列表中刪除一個或多個訂單,但是不會刪除數據庫中對應的記錄,只是將它們的customer_id外鍵設置為null,斷開和用戶的關聯。

l     orders.clear

分離用戶和訂單,就像delete(),但是如果訂單被指明為:dependent,數據庫中對應的記錄就會被刪除。

l     orders.find(options...)

發出一個find()調用,但是僅返回用戶關聯的訂單。

l     orders.build(attributes={})

構造一個新的order對象,用給定的屬性初始化,並且關聯到customer,該對象沒有保存。

l     orders.create(attributes={})

構造並且保存一個新的order對象,用給定的屬性初始化,並且關聯到customer。

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