Подтвердить что ты не робот

SessionsHelper в railstutorial.org: Должны ли помощники быть модулями общего назначения для кода, который не нужен во взглядах?

railstutorial.org имеет предложение, которое кажется мне немного странным.

Он предлагает этот код:

class ApplicationController < ActionController::Base 
  protect_from_forgery 
  include SessionsHelper 
end 

include SessionsHelper делает методы доступными из ApplicationController, да, но он делает их доступными и в любом представлении. Я понимаю, что аутентификация/авторизация является сквозной, но действительно ли это лучшее место?

Мне кажется, что это слишком широкий охват. Например, код, реализующий, скажем, before_filter, который условно перенаправляет (как это делает пример railstutorial.org) в модуле, который чаще всего содержит помощники вида, кажется удивительным.

Будет ли функциональность, не строго необходимая в представлениях, лучше размещаться в ApplicationController или где-либо еще?

Или я просто слишком много думал об этом?

4b9b3361

Ответ 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, которые фиксируют текущего пользователя (если применимо).