【问题标题】:CanCan explanation of load_and_authorize_resourcecanCan对load_and_authorize_resource的解释
【发布时间】:2015-08-30 15:46:26
【问题描述】:

我会知道load_and_authorize_resource 在内部是如何工作的。 我搜索了github页面Link并试图理解,但我没有发现任何有用的东西。我只知道load_and_authorize_resource 就像一个 before_filter 并且它(以某种方式)加载了我们在ability.rb 中编写的能力

我会更好地知道这是怎么可能的。我的意思是,我不想研究所有的 gem,但我只想看看如何在控制器中加载资源的能力,以及 load_and_authorize_resource 是否真的是一种 before_filter。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 ruby-on-rails-4 cancan


    【解决方案1】:

    免责声明:为了简单起见,我有意省略了一些对简短内部方法的调用。完整的调用链可以通过load_and_authorize_resource方法定义等获得。

    如文档中所述,load_and_authorize_resource 设置了一个 before_filter...

    # cancan/lib/cancan/controller_additions.rb
    def load_and_authorize_resource(*args)
      cancan_resource_class.add_before_filter(self, :load_and_authorize_resource, *args)
    end
    

    ...调用两个方法:load_resourceauthorize_resource

    # cancan/lib/cancan/controller_resource.rb
    def load_and_authorize_resource
      load_resource
      authorize_resource
    end
    

    为了了解他们的行为,我们将仔细研究他们两个。

    根据传递给控制器​​操作的params 哈希,load_resource 决定是否应该获取一个类的新实例(例如Post.new)或find 基于@ 的特定实例987654332@(例如Post.find(params[:id]))。该实例(或index 等操作的实例集合)被分配给控制器操作的相应实例变量。

    # cancan/lib/cancan/controller_resource.rb
    def load_resource
      unless skip?(:load)
        if load_instance?
          # here you have obtained your object, e.g. Post with id=5
          # and placed it into cancan resource_instance variable.
          # it has automatically set up @post instance variable for you
          # in your action
          self.resource_instance ||= load_resource_instance
        elsif load_collection?
          self.collection_instance ||= load_collection
        end
      end
    end
    

    稍后,authorize_resource 被调用。它的内部逻辑语法你应该很熟悉:用手检查能力看起来就像在这个方法内部发生的一样。基本上,您获取在上一步中获得的resource_instanceparams[:action],它是当前操作的名称,并检查是否可以访问给定对象的特定操作。

    # cancan/lib/cancan/controller_resource.rb
    def authorize_resource
      unless skip?(:authorize)
        # similar to what happens when you call authorize!(:show, @post)
        @controller.authorize!(authorization_action, resource_instance || resource_class_with_parent)
      end
    end
    

    只要在before_filter 内引发异常会阻止控制器操作被执行,此处未能通过授权就会将您重定向到应用程序的主页 url、显示 500 错误页面或您为CanCan::AccessDenied 处理定义的任何行为。

    另一方面,如果您成功通过了授权,您的操作代码就会被执行。现在您可以访问由CanCanload_resource 步骤设置的实例变量(例如@post)。

    【讨论】:

    • 它如何知道是获取集合,还是创建或加载实例?
    • @mwfearnley 对于:index 操作,它会加载@things,但对于其他所有操作,它会加载@thing(基于:id
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多