灿灿解释 load_and_authorize_resource
CanCan explanation of load_and_authorize_resource
我会知道 load_and_authorize_resource
是如何工作的。
我搜索了 github 页面 Link 并试图理解,但我没有找到任何有用的东西。我只知道 load_and_authorize_resource
就像一个 before_filter 并且它加载(以某种方式)我们在 ability.rb
中编写的能力
我会更清楚这是怎么可能的。我的意思是,我不想研究所有 gem,但我只想看看 cancan 如何在控制器中加载资源的能力,以及 load_and_authorize_resource
是否真的是一种 before_filter.
免责声明:为了简单起见,我特意省略了一些对短内部方法的调用。完整的调用链可以通过以下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_resource
和 authorize_resource
.
# cancan/lib/cancan/controller_resource.rb
def load_and_authorize_resource
load_resource
authorize_resource
end
为了了解他们的行为,我们将仔细观察他们。
基于传递给控制器操作的 params
哈希值,load_resource
决定是否应该获取 class 的新实例(例如 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
稍后,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
只要在 before_filter
内部引发异常会阻止控制器操作的执行,未能通过此处的授权会将您重定向到应用程序的主页 url,显示 500 错误页面或您的任何行为为 CanCan::AccessDenied
处理定义。
另一方面,如果您已成功通过授权,则会执行您的操作代码。现在您可以访问 CanCan
在 load_resource
步骤中设置的实例变量(例如 @post
)。
我会知道 load_and_authorize_resource
是如何工作的。
我搜索了 github 页面 Link 并试图理解,但我没有找到任何有用的东西。我只知道 load_and_authorize_resource
就像一个 before_filter 并且它加载(以某种方式)我们在 ability.rb
我会更清楚这是怎么可能的。我的意思是,我不想研究所有 gem,但我只想看看 cancan 如何在控制器中加载资源的能力,以及 load_and_authorize_resource
是否真的是一种 before_filter.
免责声明:为了简单起见,我特意省略了一些对短内部方法的调用。完整的调用链可以通过以下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_resource
和 authorize_resource
.
# cancan/lib/cancan/controller_resource.rb
def load_and_authorize_resource
load_resource
authorize_resource
end
为了了解他们的行为,我们将仔细观察他们。
基于传递给控制器操作的 params
哈希值,load_resource
决定是否应该获取 class 的新实例(例如 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
稍后,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
只要在 before_filter
内部引发异常会阻止控制器操作的执行,未能通过此处的授权会将您重定向到应用程序的主页 url,显示 500 错误页面或您的任何行为为 CanCan::AccessDenied
处理定义。
另一方面,如果您已成功通过授权,则会执行您的操作代码。现在您可以访问 CanCan
在 load_resource
步骤中设置的实例变量(例如 @post
)。