我只是从cancan迁移到pundit,我很喜欢使用cancan语法来检查授权:can? :show, @user
。使用pundit,将编写相同的验证policy(@user).show?
。我觉得它不太可读。所以我正在写一个2小包装器:
def can?(model, action)
policy(model).send(action)
end
def cannot?(model, action)
! can?(model, action)
end
我的问题是:在Rails 4中,2个包装器的最佳位置是什么,知道我在控制器和视图中使用它们。尚未出现在模型中,但后来可能会出现这种情况,所以请说:无处不在。
赞赏任何指针,谢谢
答案 0 :(得分:6)
我建议你将它们包装在模块中。编写类n模块并将模块放在应用程序的/lib
文件夹中。这是您在控制器,视图和模型中访问它们的最佳位置。
模块用于ruby中的3种不同的东西。首先是命名空间。在模块内部具有类或常量定义不会与该模块之外的类或常量发生冲突。像这样的东西
class Product
def foo
puts 'first'
end
end
module Affiliate
class Product
puts 'second'
end
end
p = Product.new
p.foo # => 'first'
p = Affiliate::Product.new
p.foo # => 'second'
模块的第二个用途是作为粘贴方法的地方,这些方法在其他任何地方都没有。您也可以在类中执行此操作,但使用模块类型可以告诉读取代码的人员,这些代码并不是要实现的。像这样的东西
module Foo
def self.bar
puts 'hi'
end
end
Foo.bar #=> 'hi'
最后(也是最令人困惑的)是模块可以包含在其他类中。以这种方式使用它们也被称为mixin,因为您将所有方法“混合”到您所包含的任何内容中。
module Foo
def bar
puts 'hi'
end
end
class Baz
include Foo
end
b = Baz.new
b.bar #=> 'hi'
Mixins实际上是一个比较复杂的主题,然后我在这里讨论,但更深入可能会让人感到困惑。
现在,对我来说,S3似乎真的属于控制器,因为控制器通常是处理传入和传出连接的东西。如果是这种情况,我只会在应用程序控制器上有一个受保护的方法,因为所有其他控制器都可以访问它,但仍然是私有的。
如果你确实有充分的理由将它放入模型中,我会选择mixin。像
这样的东西module AwsUtils
private
def S3
AWS::S3::Base.establish_connection!\
:access_key_id => 'Not telling',
:secret_access_key => 'Really not telling'
data = yield
AWS::S3::Base.disconnect
data
end
end
如果你把它放在lib / aws_utils.rb中,你应该可以通过在你的控制器和模型中添加include AwsUtils来使用它。 Rails知道在lib中查找类和模块,但只有在名称匹配时(大例)。我称它为AwsUtils,因为我知道当它看到(aws_utils.rb)时会看到什么轨道,说实话,我不知道它对S3Utils需要什么。
模块往往是红宝石中的那些东西之一,虽然令人惊讶,但对于新手来说却是彻头彻尾的困惑。
希望这个建议会对你有所帮助。谢谢。