最近發現又有小伙伴被 ClassName.current_user 給坑了,導致數據保存的不是預期的用戶id。所以覺得有必要詳細梳理一下這塊。
格式 | 名稱 | 是否需要初始化 | 作用范圍 | 例子 |
---|---|---|---|---|
$開頭 | 全局變量 | 不需要,初始化前值為nil | 全局 | $user |
@@開頭 | 類變量 | 需要,直接使用報錯 | 類內直接使用,外部通過類名調用 | @@user |
@開頭 | 實例變量 | 不需要,初始化前值為nil | 實例化的類內部 | @user |
大寫字母 | 常量 | 只能被賦值一次,多次賦值會警告不會報錯 | 類內部外呼均可用,外部通過類名訪問 | USER |
我們一般緩存的代碼(ClassName.current_user)
module ClassName
class << self
def current_user_id
Thread.current[:user]
end
def current_user_id=(user)
Thread.current[:user] = user
end
end
end
在這里我們緩存用的是線程實例的形式保存的,但是一般我們會使用全局變量和類變量
這兩種方式的區別如下:
全局變量或類變量
全局變量(類變量) 是在整個進程有效線程變量
Thread.current[:a]
用法,我稱之為線程變量
在當前線程有效,同一進程的其他線程不會獲取到
這兩種方式如果在多進程模式的unicorn下是一樣的
但是在多線程模式的puma下會有一些區別,第二種方式會占用多一些內存
ok,經過上面的分析我們知道了兩種緩存方式都會將緩存信息保存在進程(或線程)中,直到程序終止或者我們改變它,所以這就導致了我們使用出現問題。
因為在項目中緩存被我們用來在controller與model中傳遞數據,所以我們需要在每次訪問開始前設置上面緩存的值,否則我們就會調用到上一次訪問設置的值。