2011-02-22 57 views
1

我正在嘗試編寫一個方法,該方法將直接應用於具有HABTM關係的幾個模型以清理所有未使用的關係。如何爲所有類編寫方法

 
    def cleanup 
     self.all.each do |f| 
      if f.videos.count == 0 
       self.destroy(f) 
      end 
     end 
    end 

我在哪裏可以保存這個方法,並且這個方法甚至是正確的語法?每個模型需要

回答

4

寫入外部模塊,包括它:它理論上可以運行爲(需要導軌加載每一個),然後通過Active Record檢查視頻,使用查詢加載所有孤立記錄的速度更快,然後僅銷燬這些記錄。

猜你有標記和視頻,在這裏,而且tag_videos是你的連接表,在Rails的2.X你可以寫

def self.cleanup 
    find(:all, :conditions => "id NOT IN (select tag_id from tag_videos)").destroy_all 
end 

在Rails 3,你會寫

def self.cleanup 
    where("id NOT IN (select tag_id from tag_videos)").destroy_all 
end 
+0

我沒有寫這個作爲外部模塊,然後使用 包括我的方法 但它似乎並不想認出它仍然。 –

+1

嘗試使用'擴展MyModule'而不是'include MyModule' - 應該將方法附加到類而不是每個實例。 – dunedain289

+0

顯示您的確切模塊和您的模型 – fl00r

1

你想一個類的方法添加到標籤類,並且,而不是通過所有標籤對象迭代

 
    >>Tag.cleanup 
2

可悲的是,人們繼續使用has_and_belongs_to_many,即使它會導致這樣的孤兒。 has_many ..., :through關係可以被標記爲:dependent => :destroy以自動清理未使用的孩子。通常情況下,您會有未使用的連接記錄,並且它們令人討厭地被刪除。

你可能要做的是從SQL角度來解決這個問題,因爲如果他們的父記錄不再被定義,has_and_belongs_to_many記錄將無法訪問。就ActiveRecord而言,它們根本就不存在。使用連接模型意味着您可以隨時訪問這些數據,因爲它們都是自己的ID。

has_and_belongs_to_many關係是基於一個複合關鍵字,它使得它們成爲一個嚴重的麻煩。通常你會做DELETE FROM table WHERE id IN (...) AND ...,並確信只有目標記錄被刪除。用複合鍵你不能做到這一點。

你會發現這個工程的一個例子標籤項關係:

DELETE FROM item_tags, tags, items WHERE item_tags.tag_id=tags.id AND item_tags.item_id=items.id AND tags.id IS NULL AND items.id IS NULL 

DELETE說法可真講究,它如何運作,不給同一緯度的SELECT與加入,可以是根據需要定義爲左側或右側,內側或外側。

如果你有你的加入表中的主ID鍵,你可以很容易地做到這一點:

DELETE FROM item_tags WHERE id IN (SELECT id FROM item_tags LEFT JOIN tags ON item_tags.tag_id=tags.id LEFT JOIN items ON item_tags.item_id=items.id WHERE tags.id IS NULL AND items.id IS NULL) 

事實上,這可能是有利的主鍵添加到您的關係表,即使ActiveRecord的忽略它。

編輯:

至於你的模塊的問題,如果你堅持這種方法:

module CleanupMethods 
    def cleanup 
    # ... 
    end 
end 

class Tag 
    # Import the module methods as class methods 
    extend CleanupMethods 
end 

如果使用計數器緩存列,您可以更輕鬆地這樣做了很多,但你也必須確保你的計數器緩存是準確的。

相關問題