我会尽力解释这个问题。所以,我跳过了任何不必说明问题的代码。
我们假设一个模型:
class Model < ActiveRecord::Base
# Join class storing grants for users, e.g. 'admin', 'default'
has_many :user_grants
# Grant a user a certain grant
def grant_user(user, grant)
self.user_grants.build(:user => user, :grant => grant)
end
# Some action is done by a user, but ensure user has required grants
def action(user, action_type)
unless user_grants.find_by_user_id_and_grant(user, GrantEnum::ADMIN)
raise ModelUserNotAllowedError.new
end
...action code...
end
我跳过了User和其他一些模型的代码,因为它们与说明无关......
我们实例化代码:
1: @model = Model.new
2: @user = User.new
3: @model.grant_user(@user, GrantEnum::ADMIN)
4: @model.action(@user, ActionEnum::SOMETHING)
第4行将引发ModelUserNotAllowedError,因为此时第3行中所需的授权构建不会保留,但finder方法仅适用于持久数据。从逻辑的角度来看,不应该引发错误,因为用户被授予了足够的权限。
我正在使用 self.user_grants.build ,因为调用grant_user时可能不会保留模型。
那么,有什么选择可以让它发挥作用:
1。)实现仅使用 association.create 而不是 association.build 的代码,以确保查找程序方法是“最新的”。这也需要先拯救父母。
2.。)实现代码,通过使用 finder方法检查持久化数据,并通过循环检查来检查非持久数据,例如:鉴于上面的例子,可以检查非持久数据:
user_grants.each do |user_grant|
if user_grant.grant.eql?(GrantEnum::ADMIN)
return true
end
end
然而,提案号2似乎是一个坏主意。所以,让我们忘记吧......
还有其他选择吗?例如有没有办法让finder方法检查非持久数据?希望得到一些新的见解...
答案 0 :(得分:0)
unless user_grants.select {|user_grant| user == user && grant == GrantEnum::ADMIN}.present?
raise ModelUserNotAllowedError.new
end