Я изучаю рельсы (и Ruby) и хотел бы знать, можно ли передавать переменную между функциями контроллера.
По сути, мою проблему можно было бы возобновить следующим образом:
#controller.rb
def pageA
#assuming @variable is from a form
@variable = "foo"
if @variable == "foo"
redirect_to action: 'pageB'
else
...
end
end
def pageB
#I'd like to reuse @variable in pageB.html.erb
end
Возможно ли использовать redirect_to ? Должен ли я использовать другой подход?
Из любопытства, можно ли решить эту проблему с помощью кеша?
Это невозможно, как вы пытаетесь сделать. Ruby on Rails, как и многие другие серверные веб-фреймворки, по сути, начинает заново обрабатывать состояние для каждого запроса.
Это означает: пользователь что-то запрашивает (например, вызывает страницу A), и при запросе другой страницы (например, страницы B) состояние не сохраняется. Когда вы перенаправляете пользователя, Rails отправляет обратно команду перенаправления в браузер, а затем начинается новый запрос к серверу Rails.
Если вы хотите сохранить состояние или другие данные, вам необходимо закодировать их в URL-адресе (или использовать сеансы, например, если у вас есть система входа в систему).
В вашем случае вы можете просто добавить @variable, полученную из формы (т. е. массива params
), в перенаправление:
redirect_to action: 'pageB', variable: @variable
Тогда в методе pageB
старое значение переменной снова будет доступно как params[:variable]
.
Значение появится в URL-адресе.
Имейте в виду, что вам не следует кодировать конфиденциальные данные, такие как пароли, с помощью этого метода.
Дополнительные примеры использования метода redirect_to можно увидеть в документации Rails
Вы думаете об этом на слишком низком уровне.
Переменные — это всего лишь инструмент, который вы используете для указания данных в памяти при обработке запроса, и они не сохраняются надежно между одним запросом к другому. Они никогда не являются действительной частью конечной цели.
Переменные экземпляра не сохраняются между запросами, поскольку запросы не обрабатываются одним и тем же экземпляром контроллера.
Скорее вам нужно думать об этом с точки зрения передачи состояния (или ссылок на него) туда и обратно между сервером и клиентом. HTTP предоставляет для этого несколько механизмов, таких как URI, тело запроса и заголовки.
Данные, которые необходимо сохранять между запросами на сервере, необходимо хранить где-то, например в базе данных. В этом случае нам не нужно передавать фактические данные. Нам просто нужно сообщить серверу, что мы ищем.
В типичном случае настройки REST Rails (в виде ресурсов) сохраняются в базе данных, а затем вы просто перенаправляетесь на этот ресурс.
class ThingController < ApplicationController
# Displays a form to create a new resource
# GET /things/new
def new
@thing = Things.new
end
# Responds to form submissions
# POST /things
def create
@thing = Thing.new(thing_params)
if @thing.save
redirect_to @thing # redirect to /things/:id
else
render :new # renders the form again
end
end
# Shows a member of the collection
# GET /things/1
def show
@thing = Thing.find(params[:id])
end
private
def thing_params
params.require(:thing)
.permit(:foo, :bar)
end
end
Здесь мы просто передаем идентификатор записи как часть URL-адреса и можем использовать его в следующем запросе для получения вновь созданной записи.
Обратите внимание, что типичная ловушка для новичков в Rails — это попытка использовать перенаправление для «неудавшейся» отправки формы:
def create
@thing = Thing.new(thing_params)
@my_var= 'Hello World'
if @thing.save
redirect_to @thing, my_param: @my_var # redirect to /things/:id
else
redirect_to action: :new # OMG How do I pass all the data along?
end
end
Если пользователь пытается создать/обновить ресурс с недопустимыми данными, просто отобразите форму еще раз и вместо этого отправьте ее в качестве ответа.
Если вам действительно необходимо передать дополнительные данные с сервера вместе с перенаправлением, вы можете использовать параметры строки запроса:
# Responds to form submissions
# POST /things
def create
@thing = Things.new(thing_params)
@my_var = 'Hello World'
if @thing.save
redirect_to @thing, my_param: @my_var # redirect to /things/:id
else
render :new # renders the form again
end
end
# Shows a member of the collection
# GET /things/1
def show
@my_var = params[:my_param]
@thing = Thing.find(params[:id])
end
Любые дополнительные параметры, переданные в redirect_to
(за исключением именованных параметров, таких как status
, notice
, alert
), будут добавлены к URL-адресу в качестве параметров строки запроса. Хотя, безусловно, существуют действительные варианты использования, спросите себя, действительно ли вам это нужно, и примите во внимание безопасность.
Если вам нужен более прозрачный механизм передачи состояния браузеру и его отправки обратно, можно использовать файлы cookie . Rails предоставляет механизм сеансов, который можно использовать для хранения данных в файлах cookie на более высоком уровне.
Из любопытства, можно ли решить эту проблему с помощью кеша?
Не совсем.
Кэш — это способ повысить производительность за счет хранения данных, производство которых требует больших затрат. Любой кэш, специфичный для пользователя, по-прежнему нуждается в механизме идентификации пользователя.
В зависимости от содержимого страницы «pageB» и от того, выполняет ли действие контроллера что-то конкретное, простой
render :pageB
также может сработать.