Этот вопрос неоднократно задавался и отвечал однострочными утверждениями, такими как «потому что это явное нарушение MVC». Честно говоря, я просто не понимаю. Действительно, мне кажется, что включение сеанса в контроллер просто артефактом, который ApplicationController обращается к сетевому уровню через вызов стойки, а не мандат MVC. Позвольте мне объяснить мою проблему.Почему бы не ссылаться на хэш сеанса на уровне модели?
Выполняя аутентификацию с нуля, я обнаружил, что я мучительно и пичу повсюду из-за отсутствия возможности формулировать простые тесты (сеанс также не доступен для тестовой среды). Моя схема проверки подлинности, как и почти все, что я видел в рельсах, хотела использовать хэш сеанса в качестве слоя сохранения, чтобы сохранить идентификатор для модели пользователя «текущего пользователя». Разве это не кажется FAR БОЛЬШЕ, как модель, чем артефакт контроллера?
Код запаха очевиден, когда вы смотрите на «типичный» сеансовый контроллер (этот от Ryan Bates отличные скринкасты). Отчаявшись лопатой этой концепции с остальным, мы видим, нездоровый язык, такие как:
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
Для меня это кода запаха, явно overlogicked контроллера, который кричащий для рефакторинга! Но мы не можем. Зачем? О да, потому что это нарушение MVC, чтобы помещать ссылки на сеанс, используемые в качестве адвоката настойчивости в модели. WTF? Разве это не говорит вам что-то, что мы, похоже, хотим ПРИЗЫВАТЬ ЭТО ОТКРЫТЬ РЕСУРСЫ/сеансы?
Чтобы узнать, почему это просто болтливо, посмотрите на свои логин-взгляды - ручной код html или использование API-интерфейсов «_tags»? Если бы у нас была модель ActiveModel для выполнения этого кода, тогда код создания мог бы выглядеть как обычное основание или, возможно, даже уменьшен до однострочного ответа «reply_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 для всех этих видов! Если Recognition была моделью, она сохранялась в сеансе (или каким-то другим способом, который не должен быть ответственным за уровень контроллера), тогда вы могли бы просто использовать построитель форм или simple_form для генерации форм. Конечно, мы могли бы просто передать хэш сеанса методу класса «new_login» распознавания, скажем Recognition.on(session).new(params[:recognition])
, но это кажется более уродливым, чем это должно быть. Возможно, это присуще, поскольку мы захотим использовать ссылку current_user позже на прикладном уровне, возможно, Recognition.on(session).current_user
, аналогично тому, как можно использовать одноэлементный шаблон?
Просто попробуйте создать свой пакет аутентификации со строгим BDD, и честно скажите мне, что вы не произнесли эту порцию? Если бы у нас была модель распознавания, вся эта вещь сводилась бы к простому набору единичных тестов без хакерства. Теперь вместо этого у нас есть «единственный» вариант использования для тестирования интеграции, магические вторжения модулей ActiveController и хаки, чтобы ускорить любые приемочные испытания предиката logged_in_as.
Я думаю, что вся цель ActiveModel заключалась в том, чтобы облегчить такое переосмысление и рефакторинг. Не все модели используют базу данных «the». Почему бы не настаивать на «сеансе»?
Я использую придумывание и его родственники слишком долго, зарывая эти запахи с помощью «не испортить драгоценный камень», извините, мне не нужно смотреть на них. Больше никогда! Я думаю, что сейчас я откажусь от фанатиков. К сожалению, для меня сеанс - это уровень персистентности, который следует манипулировать на уровне модели MVC. Я полагаю, но не уверен, что причина, по которой он живет в контроллере, имеет больше общего с уродливым или изящным фактом, что контроллеры представляют собой объекты стойки, чем любая теоретическая магия MVC.
Так еще раз, есть ли более элегантный способ доступа к сеансовому слою, чем для того, чтобы иметь логику в контроллере?
Большое спасибо за замечания. Интересно, что Rails эволюционировала к однострочным строкам, которые вы описываете, хотя и не с моделями, per_se .. Механика контроллера, действительно, развилась в 3.X, чтобы использовать response_with после вызова на уровне модели. Мое предлагаемое изменение не сводит контроллер к модели, а скорее уменьшает ненужную логику в контроллере до вызова модели в ТОЧНОСТИ так же, как используется постоянный контент базы данных. – wizardwerdna