SessionsHelper в railstutorial.org: Должны ли помощники быть модулями общего назначения для кода, который не нужен во взглядах?
railstutorial.org имеет предложение, которое кажется мне немного странным.
Он предлагает этот код:
class ApplicationController < ActionController::Base
protect_from_forgery
include SessionsHelper
end
include SessionsHelper
делает методы доступными из ApplicationController
, да, но он делает их доступными и в любом представлении. Я понимаю, что аутентификация/авторизация является сквозной, но действительно ли это лучшее место?
Мне кажется, что это слишком широкий охват. Например, код, реализующий, скажем, before_filter
, который условно перенаправляет (как это делает пример railstutorial.org) в модуле, который чаще всего содержит помощники вида, кажется удивительным.
Будет ли функциональность, не строго необходимая в представлениях, лучше размещаться в ApplicationController или где-либо еще?
Или я просто слишком много думал об этом?
Ответы
Ответ 1
В самом деле, ваши чувства верны.
Я бы реализовал это наоборот: добавьте функции sign_in
и current_user
в ApplicationController
(или если вы действительно хотите: в отдельном модуле, определенном в lib
и включите его), а затем убедитесь, что метод current_user
доступен в представлении.
Короче:
class ApplicationController
helper_method :current_user
def sign_in
end
def current_user
@current_user ||= user_from_remember_token
end
end
Конечно, если у вас много кода для размещения в вашем ApplicationController
, это может стать беспорядочным. В этом случае я бы создал файл lib\session_management.rb
:
module SessionManagement
def self.included(base)
base.helper_method :current_user
end
def sign_in
..
end
def current_user
..
end
end
и внутри вашего контроллера вы можете просто написать:
class ApplicationController
include SessionManagement
end
Ответ 2
Они, похоже, используют (подлый) преимущество в том, что в Rails помощники - это просто рубиновые модули.
Поведение, которое совместно используется контроллерами в модуле, является, на мой взгляд, хорошей практикой. С другой стороны, использование этого в помощнике может ввести в заблуждение, и я бы избегал этого. Поместите его в "стандартный" модуль.
Ответ 3
Это философский вопрос на том же уровне, что и аргумент, который задает метод REST, предоставляемый в строительных лесах, и если стоило бы стоить эшафот. Вы должны учитывать тот факт, что учебная книга в RailsTutorial.org - это справочное руководство Rails-up-and-go Rails. Поэтому, для этой цели, я думаю, что она выполняет эту работу.
Однако есть ли лучшее место для размещения кода, необходимого для контроллеров и представлений? Да, есть.
- Некоторые могут последовать за Майклом Хартлом из Railstutorial и включить весь
SessionHelper
в ApplicationController
- Другие могут решить раскрывать только основные помощники, необходимые для представления, т.е.
sign_in
, sign_out
, current_user
и тому подобное.
- Я вижу предложение поместить такой код в каталог
/lib
и включить его там, где это необходимо.
Все являются жизнеспособными. В зависимости от того, что вы возьмете, это может не иметь большого значения в производительности, поскольку Ruby должен будет проанализировать файл, который вы хотите вызвать (или включить) класс, модуль или метод. Что происходит, прежде чем какой-либо код выполняется в классе, Ruby проходит через весь класс один раз, чтобы узнать, что в нем. Все зависит от того, что нужно, и дизайна своего приложения.
Ответ 4
FWIW, я сохраняю текущего пользователя в классе User:
class User < ActiveRecord::Base
cattr_accessor :current
...
end
Это может быть указано во всех трех уровнях MVC; он установлен в контроллере так (и, соответственно, при входе в систему, конечно):
def set_current_user
User.current = (session[:user_id]) ? User.find_by_id(session[:user_id]) : nil
end
Кроме всего прочего, это позволяет мне иметь журналы аудита на уровне ActiveRecord, которые фиксируют текущего пользователя (если применимо).