Rails: передача состояния пользователя между множеством контроллеров - PullRequest
0 голосов
/ 27 мая 2020

У меня есть простое приложение Rails с несколькими контроллерами, и я хочу передавать состояние пользователя между множеством различных контроллеров и представлений.

Пользователь может иметь организацию и проект.

Я хочу передать current_org и current_project через все мои контроллеры / представления, которые являются объектами для текущей организации и текущего проекта.

Как лучше всего это сделать? Я хочу уменьшить потребность в вызове базы данных при каждой загрузке страницы. Можно ли сохранить их в current_user, чтобы я мог позвонить current_user.current_project?

Ответы [ 3 ]

3 голосов
/ 27 мая 2020

Поскольку веб-запросы по сути своей не имеют состояния, для каждой новой визуализации страницы потребуется откуда-то повторно извлекать данные. Ваш метод current_user сам делает вызов базы данных за кулисами (при условии стандартной установки Devise) для загрузки пользователя при каждой загрузке страницы. Точно так же, хотя вы можете определить помощник или модуль для обмена значениями current_org и current_project, как указал Ритафул, им нужно будет делать вызовы базы данных для получения своих значений.

Или, по крайней мере, это типичный ответ Rails. У вас есть и другие варианты. Первый - использовать хранилище сеанса для хранения объектов либо через собственный маршалинг Ruby (опасный путь, как показали устаревшие системы, с которыми я работаю), либо через, возможно, JSON сериализацию:

# marshalling
def current_org
  # this will break if your organization object contains a proc, and 
  # can risk exploding your session storage if your object gets large
  session[:current_org] ||= current_user.organization
end

# serialization
def current_org
  session[:current_org] ||= current_user.organization.to_json
end

Однако объект JSON не будет моделью ActiveRecord, поэтому ваш код придется адаптировать. Вы можете технически сделать это записью через #from_json, но ваши отношения будут работать не так, как вы ожидаете, и в целом вы бы слишком далеко заблудились в этот момент.

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

1 голос
/ 27 мая 2020

Вы можете создать два метода в вашем ApplicationHelper

def current_project
  current_user.current_project
end

def current_org
  current_user.current_org
end

Они будут доступны для всех контроллеров и представлений.

Для получения дополнительной информации см. « Как использовать Rails Helpers (Полное руководство) ».

0 голосов
/ 28 мая 2020

А как насчет сеанса? Это, наверное, самый простой способ. Я помню, что делал что-то вроде этого:

  1. При использовании журналов присваивайте этот идентификатор session[:current_user_id]
  2. Каждый раз, когда пользователь переходит на другую страницу, есть частный метод, который выглядит примерно так :
def setup(id)
    @user = User.find(id)
end
Запустите этот метод в методе before_action следующим образом:
before_action do 
   setup(session[:current_session_id])
end
...