场景:我的rails系统中有几个ActiveRecord模型,都需要通过访问控制列表进行控制。我有一个很好的小ACL实现,可以实现我想要的,但是现在check-access调用都在每个受控对象类型(文档,用户等)中都是重复的。
我的直觉是将共享代码拉入模块并将其与mixin一起使用。我不确定这是可能的(或者正确的语法是什么),因为混合模块调用了ActiveRecord :: Base方法 - 有范围和has_many定义。
我想要完成的例子是:
class Document < ActiveRecord::Base
include Controlled
end
module Controlled
has_many :acls, as: :controlled
scope :accessible, ->(uid, level){where("BUNCH OF SQL HERE")}
def access_convenience_methods
#stuff to provide easy access to authorization checks
end
end
然后我会从ActiveRecord :: Base派生出一些包含Controlled的其他模型。
模块中的has_many和scope调用引起了心痛 - 我无法在混合模块中调用它们,显然这个上下文无法访问外部类方法。
欢迎任何建议。
答案 0 :(得分:2)
你是对的,因为你不能像这样从模块中调用类方法。
现在,执行此操作所需的样板代码已包含在ActiveSupport::Concern中;它完全符合你的要求。
[编辑]:我还建议你学习the boilerplate code itself,因为它非常简短易读,是Ruby元编程的一个很好的例子。
答案 1 :(得分:0)
啊哈,这显然是一个红宝石新手的失败 - 我需要将has_many和其他一次性调用放在一个包含的块中。似乎ActiveSupport :: Concern在这里使用是正确的:
module Controlled
extend ActiveSupport::Concern
included do
has_many :acls, as: :controlled
scope :accessible, ->(uid, level){where("BUNCH OF SQL HERE")}
end
def access_convenience_methods
#stuff to provide easy access to authorization checks
end
end