2

Этот вопрос неоднократно задавался и отвечал однострочными утверждениями, такими как «потому что это явное нарушение 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.

Так еще раз, есть ли более элегантный способ доступа к сеансовому слою, чем для того, чтобы иметь логику в контроллере?

ответ

1

Возможно, это только я, но я не нюхаю запах кода в этом контроллере. Я думаю, это зависит от того, что, по вашему мнению, должно идти в контроллеры по сравнению с моделями.

Я думаю, что люди воспринимают идею «тощих контроллеров» к нездоровым экстремальным временам. Да, вы хотите, чтобы все, что может быть в модели, было на модели: но существуют контроллеры для изменения моделей, основанных на состоянии приложения, и вы должны позволить им выполнить эту цель дизайна. Имея каждый контроллер будет что-то вроде:

def create 
    Creator.create(params) # Pass all params to the creator model, which will automatically detect what object you're trying to create, make it, and then render the appropriate view 
end 

def show 
    Shower.show(params) # Find the model object and the view based on the params and render them together 
end 

пренебрегает идею разделения проблем и создает кошмарные проблемы для людей, которые пытаются обновлять и поддерживать свой код. Контроллеры должны вызывать объекты модели и даже методы на этих моделях для создания и сохранения состояния приложения, а модели должны быть агностическими для состояния приложения. Если вы соедините их слишком сильно, в ваших моделях вы получите код представления и контроллера, после чего становится очень сложно определить, что в вашем приложении.

Если это то, что вы хотите, и вы считаете, что оно служит вашим целям, а затем пойдите для этого - но ваш код будет сложнее поддерживать и будет трудно понять другим людям. MVC существует, потому что это разумный способ разделить проблемы и сделать ваш код менее неожиданным для других людей.

Все это говорит о том, что модель сеанса, которую вы предлагаете, на самом деле является довольно хорошей идеей ... и, следовательно, она уже существует. ;) В структуре authlogic есть сеанс: при входе в систему с использованием authlogic вы создаете новую UserSession с объектом params. UserSessions живут в папке с образцами и существуют исключительно для абстрагирования прочной аутентификации в классе модели, поддерживающей контроллер, поэтому, если это то, что вы ищете, это уже сделано для вас! Перейдите к обзору the authlogic github repository для документации и примеров использования.

Я бы все равно уклонился от передачи какого-либо состояния контроллера в настоящую модель ActiveRecord. Позвольте вашим контроллерам манипулировать моделями и отображать результаты этих манипуляций как HTML - для чего они нужны!

+0

Большое спасибо за замечания. Интересно, что Rails эволюционировала к однострочным строкам, которые вы описываете, хотя и не с моделями, per_se .. Механика контроллера, действительно, развилась в 3.X, чтобы использовать response_with после вызова на уровне модели. Мое предлагаемое изменение не сводит контроллер к модели, а скорее уменьшает ненужную логику в контроллере до вызова модели в ТОЧНОСТИ так же, как используется постоянный контент базы данных. – wizardwerdna

Смежные вопросы