維護具有基於角色的自定義授權系統的現有Rails 2.3.x應用程序。rails habtm:返回關聯的記錄但獨佔匹配
代碼必須是這樣的:
class Role << AR:Base
# has an int attribute called "level" with higher values indicating more powerful role
habtm: members
end
class Member << AR:Base
habtm: roles
end
角色表有類似
(id, name, level)
1, admin, 1000
2, VIP, 500
3, regular, 100
4, some_other_role, 50
我有以下成員說明角色
的member1(角色:admin
,VIP
,regular
)
member2(角色:VIP
,regular
)
member3(角色:regular
)
我需要有時是拉起人員根據其分配的最高角色:
Role.admins_exclusively # should return member1
Role.vips_exclusively # should return just member2
Role.regulars_exclusively # should be just member3
無法將我的頭圍繞如何在Rails中執行此操作,而無需訴諸寫入原始SQL查詢。
有什麼建議嗎?
更新:2012年3月29日
這是我的解決方案基本上確定了一堆爲每個角色這樣的(()使用以及一些動態規劃與define_method一起)的方法。
class Member < AR:Base
define_method :vips_exclusively do
scoped :joins => :roles,
:group => 'members.id',
:having => ["max(roles.level) = ?", Role.find_by_name('vip').level]
end
end
但是,我發現舊的rails 2.3.x有一個問題。例如,在Member.vips_exclusively上調用size()或count()會產生不正確的總數。調用length()會產生正確的結果,但建議儘可能使用size()。
查看Rails代碼後,看起來像:group
和:having
之類的選項在scoped()中設置時不會傳遞給count()。用named_scopes替換調用範圍()(更新:不是)解決了計數問題。
因此,我將克里斯的建議與一些編輯結合起來,以保證正確性和簡潔性。謝謝!
另一個更新。
其實問題:group和:沒有被傳遞也在named_scoped實現中。
果然,這裏有一張陳舊的票據,沒有任何修復,使它成爲Rails源代碼樹(至少不在2.3.x分支中)。
https://rails.lighthouseapp.com/projects/8994/tickets/1349-named-scope-with-group-by-bug
太棒了......