2014-02-24 108 views
0

我有三個型號無法通過

主題

class Subject < ActiveRecord::Base 
    has_many :enrollments, dependent: :destroy 
    has_many :students, through: :enrollments, source: :students 

用戶

class User < ActiveRecord::Base 
    has_many :enrollments, foreign_key: 'student_id', dependent: :destroy 
    has_many :subjects, through: :enrollments 

招生

class Enrollment < ActiveRecord::Base 
    belongs_to :subject 
    belongs_to :student, class_name 'User' 

讓我們說,首先我做

刪除的has_many
User.count # return 23 

它返回23,這很好。但是,如果我做

c = Subject.first # Any subject 
s = c.students 
s.size   # It returns 1, so it does have AR, and I can see the users. 
s.class   # For some reason it is an Array, not an AR, but rails is probably lying 
s.destroy_all # Shows it destroys it successfully 

s    # Returns [] 
c.students  # Returns [] 

但問題是,當我打電話

User.count # It still return 23 

計數是錯誤的。它應該是22.我仍然可以使用User.find(delete_student_id) 仍然可以看到記錄。當我使用User.count時,這不是一個緩存問題,因爲我使用User.all.size,它給出了23.

我想讓學生實際上從數據庫中刪除,使用subject.students.destroy_all

現在我使用

User.where(id: s.pluck('users.id')).destroy_all 

s.each do |student| 
    student.destroy 
end 

那些將工作,但一個大碼的氣味給我。

+0

s是用戶/學生的數組,你是什麼意思? – sonnyhe2002

+0

[destroy_all的文檔](http://apidock.com/rails/v3.2.13/ActiveRecord/Associations/CollectionAssociation/destroy_all)(或[destroy_all](http://apidock.com/rails/v3.2.13/ActiveRecord/Relation/destroy_all))在@ sonnyhe2002的一面。由於代碼片段非常短,所以我最好的選擇是[事務](http://apidock.com/rails/v3.2.13/ActiveRecord/Transactions/ClassMethods),以防止更改被保留。 – TheConstructor

回答

0

destroy_all只會按照mikerz的建議刪除註冊。我重新創建你的設置和運行軌道控制檯:

>> Subject.first.students.destroy_all 
Subject Load (1.0ms) SELECT `subjects`.* FROM `subjects` LIMIT 1 
User Load (0.0ms) SELECT `users`.* FROM `users` INNER JOIN `enrollments` ON `users`.`id` = `enrollments`.`student_id` WHERE `enrollments`.`subject_id` = 1 
    (0.0ms) BEGIN 
    Enrollment Load (0.0ms) SELECT `enrollments`.* FROM `enrollments` WHERE `enrollments`.`subject_id` = 1 AND `enrollments`.`student_id` = 1 
    SQL (22.0ms) DELETE FROM `enrollments` WHERE `enrollments`.`id` = 2 
    (91.0ms) COMMIT 
[#<User id: 1, name: "a user", created_at: "2014-02-24 21:49:05", updated_at: "2014-02-24 21:49:05">] 

因此,儘管合同返回已刪除的對象似乎有點關閉:through關聯。離開你

Subject.first.students.select.destroy_all 

(其中選擇是切換到刪除用戶魔術),

Subject.first.students.each { |student| student.destroy } 

User.destroy_all(id: Subject.first.students.collect { |student| student.id }) 

而且是有depent: :destroy前兩個那些三似乎運行相同數量的SQL,而第三個將加載每個User兩次。
每個變體一次摧毀一個註冊和一個用戶,而不是所有註冊(甚至不是一個用戶的註冊)或一個註釋中的所有用戶。此行爲在destroy_all -API文檔中描述:

注意:實例化,回調執行和每個記錄的刪除在一次刪除多條記錄時可能非常耗時。它爲每個記錄至少生成一個SQL DELETE查詢(或者可能更多,以執行您的回調)。如果您想快速刪除多行,而不關心它們的關聯或回調,請改用delete_all。

+0

select.destroy_all是可以接受的。其他人,你可以使用採摘而不是採集。 – sonnyhe2002

0

您需要依賴破壞用戶更新您的Enrollment類:

class Enrollment < ActiveRecord::Base 
    belongs_to :subject 
    belongs_to :student, class_name 'User', dependent: :destroy 
end 

不過,我不建議這樣做,因爲它會拋出一個錯誤每當有User在多個Subjects就讀。

如果你想刪除任何User沒有註冊,我會使用after_destroy回調Enrollment

+0

這樣做,摧毀了學生。但如果主體被毀壞或註冊被破壞,那麼這個學生就會被銷燬,這是我不能允許的。現在我正在學students.each {| student | student.destroy} – sonnyhe2002