gpt4 book ai didi

ruby-on-rails - 让通用的 before_filters 不那么难看?

转载 作者:太空宇宙 更新时间:2023-11-03 17:13:19 27 4
gpt4 key购买 nike

我有一些之前的过滤器,用于在逐个资源级别上控制对资源的访问。基本思路如下:

  1. 用户可以是 useradmin,并且可以访问基于“accesses”表的特定资源。
  2. 资源/方法的访问权限可以限制为 adminowner、特定用户或所有人。

一些代码示例可以很好地说明这一点。我们有 4 个应用程序级方法,它们使用 before_filter 添加到调用链中。这是示例 Controller 类的顶部:

before_filter :require_user
before_filter :get_object, :only=>[:show, :edit, :update, :destroy]
before_filter :require_access, :only=>[:show]
before_filter :require_owner, :only=>[:edit, :update, :destroy]

如您所见,首先我们要求用户登录才能访问此 Controller 中的任何方法。这里有 3 个方法(在 application.rb 中定义),以便您可以看到它们的样子:

 private
def get_object
begin
class_name = controller_name.gsub("Controller","").downcase.singularize
instance_variable_set "@#{class_name}".to_sym, class_name.capitalize.constantize.find(params[:id])
rescue
flash[:error] = "You do not have access to that #{class_name}."
redirect_to "/" and return
end
end

private
def require_owner
class_name = controller_name.gsub("Controller","").downcase.singularize
accessable = instance_variable_get("@#{class_name.downcase}")
unless accessable.user == current_user
flash[:error] = "You do not have access to that #{class_name.downcase}."
redirect_to "/" and return
end
end

private
def require_access
class_name = controller_name.gsub("Controller","").downcase.singularize
accessable = self.instance_variable_get("@#{class_name.downcase}")
unless current_user.has_access?(accessable)
flash[:error] = "You do not have access to that #{class_name.downcase}."
redirect_to "/" and return
end
end

据我所知,从编码的角度来看,这一切都很好。但这太他妈的丑陋了!特别是以下几行:

 class_name = controller_name.gsub("Controller","").downcase.singularize
obj = instance_variable_get("@#{class_name.downcase}")

 instance_variable_set "@#{class_name}".to_sym, class_name.capitalize.constantize.find(params[:id])

有谁知道我在这里做的事情有更优雅的方式吗?

最佳答案

我不知道是否有真正干净的方法来做到这一点,但这里有一些建议:

首先,创建一个 Controller ResourceController,并让所有相关的 Controller 继承自它。 (如果此授权适用于所有 Controller ,您可以只使用 ApplicationController。)

现在,在名为 model_name 的父类(super class)中实现一个私有(private)方法(就像您的 class_name)这样您就不必在每次需要时都派生它。 并且,您应该能够通过简单地执行以下操作来推导出它:

def model_name
controller_name.classify
end

您还可以在返回实际类的父类(super class)中实现 model 方法:

def model
model_name.constantize
end

此时你不妨也添加这样的内容:

def current_object
model.find(params[:id])
end

def current_object_var_name
"@#{model_name.underscore}"
end

除了始终使用 @object 或类似的东西之外,我没有看到使用 instance_variable_get/set 的快速方法。但如果您不想这样做,这些行现在更简单了一些:

instance_variable_set current_object_var_name, current_object
obj = instance_variable_get(current_object_var_name)

此时您的代码应该更具可读性,也更漂亮一些。

您可能还想查看一些最近的 Rails 授权插件在做什么,特别是 cancandeclarative_authorization .

关于ruby-on-rails - 让通用的 before_filters 不那么难看?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1929782/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com