Стиль кодирования довольно важен. Большинство крупнейших строительных компаний имеет документ, который определяет необходимые соглашения о присвоении имен, комментируя инструкции и другие небольшие вещи сделать с инструкциями по архитектуре и стилем кода.
, Весь из которого очень хорош и помогает способствовать рабочей среде, в который у членов команды могут быть хорошие ожидания какой, их коллеги кодируют, будет похож.
Просто удостоверяются, что это не переходит к уровню менеджера, вынуждающего разработчика вносить изменение в обзоре кода от чего-то вроде этого:
if( someBool() ) doSomething();
else doNothing();
К чему-то вроде этого просто, потому что они "чувствуют", что это - "лучший" стиль:
if( someBool() )
{
doSomething();
}
else
{
doNothing();
}
Просто имейте причины лучше, чем персональное предпочтение требований стиля, и мы можем все быть более счастливыми.
Я бы сказал, что ваши инстинкты держать current_user
вне модели верны
Как и Дэниел, я сторонник худых контроллеров и толстых моделей, но есть еще и четкое разделение обязанностей. Назначение контроллера - управлять входящим запросом и сеансом. Модель должна быть способна ответить на вопрос «Может ли пользователь x сделать y с этим объектом?», Но для нее бессмысленно ссылаться на current_user
. Что делать, если вы находитесь в консоли? Что, если это задание cron?
Во многих случаях с правильным API разрешений в модели это можно решить с помощью однострочных before_filters
, которые применяются к нескольким действиям.
Что ж, я предполагаю, что current_user
, наконец, является экземпляром пользователя, так почему бы не Чтобы добавить эти разрешения в модель Пользователь
или в модель данных, если вы хотите, чтобы разрешения применялись или запрашивались?
Я предполагаю, что вам нужно как-то реструктурировать свою модель и передать текущему пользователю в качестве параметра, например:
class Node < ActiveRecord
belongs_to :user
def authorized?(user)
user && ( user.admin? or self.user_id == user.id )
end
end
# inside controllers or helpers
node.authorized? current_user
Я использую плагин декларативной авторизации, и он делает что-то похожее на то, что вы упомянули, с current_user
Он использует before_filter
чтобы вытащить current_user
и сохранить его там, где слой модели может получить к нему доступ. Выглядит это так:
# set_current_user sets the global current user for this request. This
# is used by model security that does not have access to the
# controller#current_user method. It is called as a before_filter.
def set_current_user
Authorization.current_user = current_user
end
Однако я не использую модельные возможности декларативной авторизации. Я сторонник подхода «Тощий контроллер - толстая модель», но мне кажется, что авторизация (как и аутентификация) - это то, что принадлежит уровню контроллера.
и он делает что-то похожее на то, что вы упомянули с current_user
. Он использует before_filter
для извлечения current_user
и сохранения его там, где слой модели может добраться до него. Выглядит это так:
# set_current_user sets the global current user for this request. This
# is used by model security that does not have access to the
# controller#current_user method. It is called as a before_filter.
def set_current_user
Authorization.current_user = current_user
end
Однако я не использую модельные возможности декларативной авторизации. Я сторонник подхода «Тощий контроллер - толстая модель», но мне кажется, что авторизация (как и аутентификация) - это то, что принадлежит уровню контроллера.
и он делает что-то похожее на то, что вы упомянули с current_user
. Он использует before_filter
, чтобы вытащить current_user
и сохранить его там, где слой модели может добраться до него. Выглядит это так:
# set_current_user sets the global current user for this request. This
# is used by model security that does not have access to the
# controller#current_user method. It is called as a before_filter.
def set_current_user
Authorization.current_user = current_user
end
Однако я не использую модельные возможности декларативной авторизации. Я сторонник подхода «Тощий контроллер - толстая модель», но мне кажется, что авторизация (как и аутентификация) - это то, что принадлежит уровню контроллера.
Это есть в моем приложении. Он просто ищет текущий сеанс контроллера [: user] и устанавливает его в переменную класса User.current_user. Этот код работает в продакшене и довольно прост. Хотел бы я сказать, что это я придумал, но я полагаю, что позаимствовал это у интернет-гения в другом месте.
class ApplicationController < ActionController::Base
before_filter do |c|
User.current_user = User.find(c.session[:user]) unless c.session[:user].nil?
end
end
class User < ActiveRecord::Base
attr_accessor :current_user
end
Хотя на этот вопрос многие ответили, я просто хотел быстро добавить свои два цента.
Использование подхода #current_user в модели User следует применять с осторожностью из-за безопасности потоков .
Можно использовать класс / одноэлементный метод для User, если вы не забыли использовать Thread.current как способ хранения и получения ваших значений. Но это не так просто, потому что вам также нужно сбросить Thread.current, чтобы следующий запрос не унаследовал разрешения, которых он не должен.
Я пытаюсь сделать следующее: если вы сохраняете состояние в классе или синглтоне переменных, помните, что вы бросаете поток безопасности в окно.