Этот вопрос неоднократно задавался и отвечался однострочными утверждениями, такими как «потому что это очевидное нарушение MVC».Честно говоря, я просто не понимаю.Действительно, мне кажется, что помещение сессии в контроллер просто артефакт, с которым ApplicationController сталкивается с сетевым уровнем посредством вызова стойки, а не мандата MVC.Позвольте мне объяснить мою проблему.
Свертывая аутентификацию с нуля, я обнаружил, что мучаюсь и всплываю повсюду из-за отсутствия способности формулировать простые тесты (сеанс также недоступен для инфраструктуры тестирования).Моя схема аутентификации, как почти все, что я видел в rails, хотела использовать сессионный хэш в качестве постоянного слоя, чтобы сохранить идентификатор для модели User «текущего пользователя».Разве это не кажется НАМНОГО больше похожим на модель, чем на артефакт контроллера?
Запахи кода очевидны всякий раз, когда вы смотрите на «типичный» контроллер сессий (этот от превосходных скринкастов Райана Бейтса).Отчаянно пытаясь перенести эту концепцию в состояние покоя, мы видим нездоровый язык, такой как:
def create
user = User.find_by_email(params[:session][:email])
if user && user.authenticate(params[:session][:password])
session[:user_id] = user.id
redirect_to root_url, notice: "Logged in!"
else
flash.now.alert = "Email or password is invalid"
render "new"
end
end
Для меня это запах кода, явно перегруженный контроллер, который кричит о рефакторинге!Но мы не можем.Зачем?Ах, да, потому что MVC - это нарушение ссылки на сеанс, который используется в качестве настойчивого юриста в модели.WTF?Разве это не говорит вам что-то, что мы, похоже, хотим ВЫЗЫВАТЬ ЭТОТ REST RESOURCE / сеансы?
Чтобы понять, почему это просто странно, посмотрите на свои виды входа в систему - html с ручной кодировкой или используйтеAPI "_tags"?Если бы у нас была модель ActiveModel, чтобы сделать этот код, то код создания мог бы выглядеть как обычный скаффолдинг или, возможно, даже уменьшаться до однострочного "response_with".
def create
recognition = Recognition.new(params[:user])
if recognition.save
redirect_to root_url, :notice => "Thank you for signing up!"
else
render "new"
end
end
Затем взгляните наhtml с ручной кодировкой для всех этих просмотров!Если Распознавание было моделью, сохраняемой сессией (или каким-либо другим способом, который не должен быть обязанностью уровня контроллера в любом случае), то вы могли бы просто использовать построитель форм или simple_form для генерации форм.Конечно, мы могли бы просто передать хеш сессии методу распознавания класса "new_login", скажем, Recognition.on(session).new(params[:recognition])
, но это кажется уродливее, чем должно быть.Возможно, это присуще, поскольку мы захотим использовать ссылку на current_user позже на прикладном уровне, возможно, Recognition.on(session).current_user
аналогично тому, как можно использовать одноэлементный шаблон?
Просто попробуйте собрать свой пакет аутентификации со строгимBDD, и честно скажи мне, что ты не пронзил эту часть?Если бы у нас была модель Recognition, вся эта вещь была бы сведена к простому набору модульных тестов без хакерских атак.Теперь вместо этого у нас есть «единственный» вариант использования для интеграционного тестирования, магических вторжений модулей ActiveController и взломов для ускорения любого приемочного тестирования предиката logged_in_as.
Я думаю, что весь смысл ActiveModel заключался в том, чтобы облегчить это.вид переосмысления и рефакторинга.Не все модели используют «базу данных».Почему бы не продолжать "сеанс"?
Я слишком долго использовал devise и его родственников, хороня эти запахи под предлогом «не связывайся с драгоценными камнями», извините, мне не нужно на них смотреть.Больше никогда!Я думаю, что теперь я собираюсь отказаться от фанатиков.Извините, для меня сессия - это постоянный уровень, которым нужно манипулировать на уровне модели MVC.Я полагаю, но не уверен, что причина, по которой он живет в земле контроллеров, больше связана с уродливым или изящным фактом, что контроллеры являются стоечными объектами, чем любая теоретическая магия MVC.
Итак, еще раз, есть ли ещеэлегантный способ получить доступ к уровню сеанса, чем иметь логику в контроллере для этого?