CanCan对load_and_authorize_resource的解释

Vit*_*ito 13 ruby-on-rails cancan ruby-on-rails-3 ruby-on-rails-4

我会知道load_and_authorize_resource里面的作品.我搜索了github页面链接并试图找不到,但我没有发现任何有用的东西.我只是理解load_and_authorize_resource这就像是before_filter并且它(以某种方式)加载了我们在ability.rb中编写的能力.

我会更清楚这是如何可能的.我的意思是,我不想研究所有的宝石,但我想知道如何在控制器中加载资源的能力,以及它load_and_authorize_resource是否真的是一种before_filter.

two*_*ves 18

免责声明:为了简单起见,我省略了一些有意短暂内部方法的调用.可以通过以下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
Run Code Online (Sandbox Code Playgroud)

...它调用两种方法:load_resourceauthorize_resource.

# cancan/lib/cancan/controller_resource.rb
def load_and_authorize_resource
  load_resource
  authorize_resource
end
Run Code Online (Sandbox Code Playgroud)

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

基于params传递给控制器​​操作的哈希,load_resource决定是否应该获取类的新实例(例如Post.new)或find基于params[:id](例如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
Run Code Online (Sandbox Code Playgroud)

后来,authorize_resource被召唤.它的内部逻辑语法应该是您熟悉的:用手检查能力看起来与此方法内部发生的情况相同.基本上,您resource_instance在上一步获取一个获取的,params[: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
Run Code Online (Sandbox Code Playgroud)

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

另一方面,如果您成功通过授权,则会执行您的操作代码.现在您可以访问@postCanCanload_resource步骤设置的实例变量(例如).

  • 它如何知道是获取一个集合,还是创建或加载一个实例? (2认同)