我想在Ruby on Rails應用程序中記錄用戶的操作。在觀察者中訪問會話的好主意嗎?
到目前爲止,我有一個模型觀察者,在更新和創建後將日誌插入數據庫。爲了存儲哪個用戶執行了記錄的操作,我需要訪問會話,但這是有問題的。
首先,它打破了MVC模型。其次,技術從惡作劇到奇怪,甚至可能將實施與Mongrel服務器捆綁在一起。
什麼是正確的方法?
我想在Ruby on Rails應用程序中記錄用戶的操作。在觀察者中訪問會話的好主意嗎?
到目前爲止,我有一個模型觀察者,在更新和創建後將日誌插入數據庫。爲了存儲哪個用戶執行了記錄的操作,我需要訪問會話,但這是有問題的。
首先,它打破了MVC模型。其次,技術從惡作劇到奇怪,甚至可能將實施與Mongrel服務器捆綁在一起。
什麼是正確的方法?
我覺得這是一個非常有趣的問題。我會在這裏大聲地想一想......
最終,我們面臨的是決定違反設計模式可接受的實踐,以實現一組特定的功能。因此,我們必須問自己
1)什麼是將不違反MVC模式
2)什麼是將違反MVC模式
3可能的解決方案可能的解決方案)哪個選項最好?我認爲設計模式和標準實踐非常重要,但同時如果堅持讓它們使您的代碼更加複雜,那麼正確的解決方案很可能違反了實踐。有些人可能會不同意我的看法。
讓我們先考慮#1。
關閉我的頭頂,我認爲以下可能的解決方案
A)如果你是誰是執行這些操作,應此數據存儲模型中的任何方式真正感興趣的?它會將這些信息提供給您的觀察員。這也意味着你的ActiveRecord類的其他前端調用者可以獲得相同的功能。 B)如果你不是真正有興趣瞭解誰創建了一個條目,但更感興趣的是自己記錄Web操作,那麼你可能會考慮「觀察」控制器的操作。自從我引入Rails源代碼以來,已經有一段時間了,所以我不確定他們的ActiveRecord :: Observer是否「觀察」了模型,但是您可能可以將其調整爲控制器觀察者。從這個意義上講,您不再觀察模型,並且將會話和其他控制器類型的數據信息發送給該觀察者是有意義的。 C)最簡單的解決方案,用最少的「結構」,就是簡單地將你的日誌代碼放在你正在觀察的動作方法的最後。
現在考慮選項#2,打破MVC的做法。
A)正如你所建議的,你可以找到讓你的模型觀察者有權訪問會話數據的方法。您已將您的模型與業務邏輯相結合。
B)可沒想到這裏的任何人:)
我個人的傾向,而不用知道了細節你的項目,或者是1A,如果我要附加的人的記錄,或1C如果有隻有幾個我對此感興趣的地方。如果您真的想爲您的所有控制器和操作提供強大的日誌記錄解決方案,則可以考慮1B。
讓模型觀察者發現會話數據有點「臭」,如果您嘗試在任何其他項目/情境/上下文中使用您的模型,可能會中斷。
你是對的,它打破了MVC。我建議在你的控制器中使用回調函數,主要是因爲有些情況(比如一個保存被調用但驗證失敗的模型),你不希望觀察者記錄任何東西。
這是一個棘手的情況。你幾乎要違反MVC才能很好地工作。
我會做這樣的事情:
class MyObserverClass < ActiveRecord::Observer
cattr_accessor :current_user # GLOBAL VARIABLE. RELIES ON RAILS BEING SINGLE THREADED
# other logging code goes here
end
class ApplicationController
before_filter :set_current_user_for_observer
def set_current_user_for_observer
MyObserverClass.current_user = session[:user]
end
end
這是一個有點哈克,但比許多其他Rails核心的事情,我已經看到了它沒有更多的哈克。
所有你需要做的(如果你在JRuby上運行反正這只是問題),使其線程是改變cattr_accessor是一個適當的方法,並將它保存它在線程本地存儲數據
在過去,當做這樣的事情時,我傾向於擴展用戶模型類以包含'當前用戶'的想法
看看以前的答案,我看到建議來存儲實際活動記錄用戶在會話中。這有幾個缺點。
因此,在請求開始時(在過濾器中),您從會話獲取user_id並讀取用戶,並設置User.current_user。
事情是這樣的......
class User cattr_accessor :current_user end class Application before_filter :retrieve_user def retrieve_user if session[:user_id].nil? User.current_user = nil else User.current_user = User.find(session[:user_id]) end end end
從那時起,它應該是微不足道的。
我找到了一個乾淨的方式來完成我選擇的答案建議的內容。
http://pjkh.com/articles/2009/02/02/creating-an-audit-log-in-rails
此解決方案使用審計日誌模型以及一個TrackChanges模塊來跟蹤功能添加到任何模型。它仍然需要您在更新或創建時向控制器添加一行。
我想到的可能是1A的東西,也許是因爲它的簡單性。 – Jaryl 2008-09-25 15:29:23