У меня есть несколько фильтров до этого, которые я использую для контроля доступа к ресурсам на уровне ресурсов. Основная идея заключается в следующем:
- Пользователь может быть
user
или admin
и может иметь доступ к определенным ресурсам на основе таблицы «доступов».
- Ресурсы / методы могут быть ограничены в доступе
admin
, owner
, определенным пользователям или всем.
Это лучше всего иллюстрируется некоторыми примерами кода. У нас есть 4 метода уровня приложения, которые добавляются в цепочку вызовов с помощью before_filter
. Вот вершина примера класса контроллера:
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]
Как видите, сначала мы требуем, чтобы пользователь вошел в систему для доступа к любому методу в этом контроллере. Вот 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}")
OR
instance_variable_set "@#{class_name}".to_sym, class_name.capitalize.constantize.find(params[:id])
Кто-нибудь знает немного более изящный способ сделать то, что я здесь делаю?