2012-06-01 48 views
3

我正在使用Rails 1.2.3(是的,我知道),並且對於has_many如何處理對象持久性感到困惑。何時保存has_many關係中的Active Record對象?

例如起見,我將用這個作爲我的聲明:

class User < ActiveRecord::Base 
    has_many :assignments 
end 

class Assignment < ActiveRecord::Base 
    belongs_to :user 
end 

據我瞭解,這將產生,除其他外,方法User#assignments.build,它創建了一個Assignment對象,其user_id是接收實例的id(以及其他字段如參數中指定的那樣),但不會將此對象保存在數據庫中。稍後可以通過調用Assignment#save!來保存該對象。

然而,Pragmatic Programmers的敏捷Web開發使用Rails,第二版,這是我一直在使用的指導和參考,說:

如果在數據庫中存在的父對象,然後將一個孩子 對象添加到集合中會自動保存該孩子。

這裏似乎有矛盾。我想知道的是:

  • 如果我做some_user.assignments.build,是Assignment對象保存?
  • 如果我做some_user.assignments << Assignment.new,是否保存了Assignment對象?
  • 如果我做some_user.assignments << Assignment.create,是兩個數據庫調用,還是隻有一個?如果我在創建它並將其添加到some_user.assignments之間時修改了Assignment對象,怎麼辦?
  • 如果我的save!Assignment對象的相應User尚未保存在數據庫中會發生什麼情況?

P.S.我之所以不使用User#assignments.create是因爲它不允許我將初始化用於外部方法,我希望能夠做到這一點。我也不想多次訪問數據庫。

回答

17

注意:以下所有控制檯測試都在Rails 3中運行。您可能會在Rails 1中得到不同的輸出結果,您必須自行運行測試以進行比較。

如果您想了解Active Record幕後發生的事情,讓您的滑軌控制檯非常有用。下面是與非保存的對象會發生什麼:

u = User.new 
#<User id: nil, name: nil, created_at: nil, updated_at: nil> 

u.assignments.build(:name => "example") 
#<Assignment id: nil, name: "example", user_id: nil, created_at: nil, updated_at: nil> 

u.save 
#SQL (0.2ms) INSERT INTO `users` (`created_at`, `name`, `updated_at`) VALUES ('2012-06-01 19:25:45', NULL, '2012-06-01 19:25:45') 
#SQL (0.2ms) INSERT INTO `assignments` (`created_at`, `name`, `updated_at`, `user_id`) VALUES ('2012-06-01 19:25:45', 'example', '2012-06-01 19:25:45', 1) 

正如你所看到的,兩者都在同一時間保存新的用戶被保存時。現在讓我們嘗試情景二:

u = User.create!(:name => "test") 
#SQL (0.2ms) INSERT INTO `users` (`created_at`, `name`, `updated_at`) VALUES ('2012-06-01 19:27:21', 'test', '2012-06-01 19:27:21') 
#<User id: 2, name: "test", created_at: "2012-06-01 19:27:21", updated_at: "2012-06-01 19:27:21"> 

u.assignments.build(:name => "example") 
#<Assignment id: nil, name: "example", user_id: 2, created_at: nil, updated_at: nil> 

所以,從這個我們可以得出結論:

如果我做some_user.assignments.build,是分配對象得救嗎?

都能跟得上

如果我不some_user.assignments < < Assignment.new,在分配對象保存?

不,這正是assignments.build所做的,沒有區別。

如果我不some_user.assignments < < Assignment.create,是兩個數據庫調用製作,或只是一個?

只是任務。

如果我在創建它並將它添加到some_user.assignments之間修改了Assignment對象,那麼怎麼辦?

不明白,對不起。

如果我保存會怎麼樣!其相應用戶尚未保存在數據庫中的Assignment對象?

它被保存到沒有user_id的數據庫中。然後,當您調用用戶保存時,會向該分配發出更新命令以添加用戶標識。這是在控制檯:

u = User.new(:name => "John Doe") 
#<User id: nil, name: "John Doe", created_at: nil, updated_at: nil> 

a = Assignment.new(:name => "test") 
#<Assignment id: nil, name: "test", user_id: nil, created_at: nil, updated_at: nil> 

u.assignments << a 
#[#<Assignment id: nil, name: "test", user_id: nil, created_at: nil, updated_at: nil>] 

a.save! 
#SQL (0.2ms) INSERT INTO `assignments` (`created_at`, `name`, `updated_at`, `user_id`) VALUES ('2012-06-01 19:33:24', 'test', '2012-06-01 19:33:24', NULL) 

a.user_id 
#nil 

u.save! 
#INSERT INTO `users` (`created_at`, `name`, `updated_at`) VALUES ('2012-06-01 19:33:36', 'John Doe', '2012-06-01 19:33:36') 
#UPDATE `assignments` SET `user_id` = 3, `updated_at` = '2012-06-01 19:33:36' WHERE `assignments`.`id` = 3 

希望這有助於。

+0

謝謝。當它說孩子被自動保存時,你知道這本書是什麼意思嗎? – Taymon

+0

當然。這意味着孩子在保存父母后自動保存。因此,您不必在保存任務和用戶時調用保存。用戶同時也會自動保存分配,但在保存用戶之前不會自動保存。 – roflmao

相關問題