简体   繁体   English

从Ruby模块中的mixed调用类方法

[英]Calling class methods from mixed in module in ruby

The scenario: I have a couple of ActiveRecord models in my rails system that all need to be controlled via an access control list. 场景:我的Rails系统中有几个ActiveRecord模型,所有这些都需要通过访问控制列表进行控制。 I have a nice little ACL implementation that does what I want, but right now the check-access calls are all duplicated in each controlled object type (document, user, etc). 我有一个不错的小ACL实现,可以实现我想要的功能,但是现在,检查访问调用在每种受控对象类型(文档,用户等)中都重复了。

My intuition is to pull that shared code into a module and use it with a mixin. 我的直觉是将共享代码放入模块中,并与mixin一起使用。 I'm not sure this is possible (or what the right syntax is), because the mixed-in module has calls to ActiveRecord::Base methods - there's scope and has_many definitions. 我不确定这是否可行(或正确的语法是什么),因为混合模块调用了ActiveRecord :: Base方法-存在作用域和has_many定义。

The example of what I'd like to accomplish is here: 我要完成的示例如下:

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

And then I'd have a few other models that derive from ActiveRecord::Base that include Controlled. 然后,我将从ActiveRecord :: Base派生出其他一些模型,这些模型包括Controlled。

It's the has_many and scope calls in the module that are causing heartache - I can't call them from within the mixed-in module, apparently this context doesn't have access to the outer class methods. 导致心痛的是模块中的has_many和scope调用-我无法从混合模块内部调用它们,显然,此上下文无法访问外部类方法。

Any advice is welcome. 欢迎任何建议。

You are correct in that you can't just call class methods from the module like that. 您是正确的,因为您不能像这样从模块中调用类方法。

Nowadays the boilerplate code required to do this has been wrapped into ActiveSupport::Concern ; 如今,执行此操作所需的样板代码已包装到ActiveSupport :: Concern中 it does exactly what you want. 它确实满足您的需求。

[EDIT]: I also suggest you should study the boilerplate code itself , as it's pretty short and readable and a good example of Ruby metaprogramming. [编辑]:我还建议您研究样板代码本身 ,因为它很简短,易读,并且是Ruby元编程的一个很好的例子。

Aha, this is clearly a ruby newbie failure here - I need to put the has_many and other one-off calls inside an included block. 啊哈,这显然是红宝石的新手失败-我需要将has_many和其他一次性调用放入包含的块中。 It seems like ActiveSupport::Concern is precisely the right thing to use here: 似乎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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM