1

我刚刚从 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 中,两个包装器的最佳位置是什么,知道我在控制器和视图中使用它们。尚未在模型中,但以后可能会成为这种情况,所以可以说:无处不在。

  • 如果我使用视图助手,它们仅在视图中可用
  • 如果我使用应用程序控制器帮助程序,则它们在测试视图时不能被 rspec 使用,我相信它们在模型中不可用

任何指针表示赞赏,谢谢

4

1 回答 1

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'

最后(也是最令人困惑的)是模块可以包含在其他类中。以这种方式使用它们也称为混入,因为您将所有方法“混入”到您所包含的任何内容中。

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 中,您应该能够通过在控制器和模型中添加包含 AwsUtils 来使用它。Rails 知道在 lib 中查找类和模块,但前提是名称匹配(在大写情况下)。我称它为 AwsUtils 是因为我知道 rails 看到它时会寻找什么 (aws_utils.rb),老实说,我不知道 S3Utils 需要什么。

模块往往是 ruby​​ 中的一种,虽然令人惊叹,但对新手来说却是完全莫名其妙的。

希望这个建议对你有帮助。谢谢。

于 2013-07-28T10:49:01.653 回答