Я прекрасно понимаю, как хранить id в сессии. Вы просто заходите в свой контроллер и делаете что-то вроде
@object = Object.find_by(params[:id)
session[:first_object] = @object
Но что, если у меня в поле зрения целая куча разных объектов, и мне нужно передать сеансу только один? Я не могу использовать hidden_fields
. Обычно я передаю его в качестве аргумента form_for
, но я бы предпочел, чтобы идентификатор объекта не отображался в URL-адресе.
<% @owned_objects.each do |obj| %>
<%= form_for [obj, @wizard], as: :wizard, url: object_one_wizard_path(obj) do |f| %>
bla bla
<% end %>
@Mark Мне просто нужен идентификатор любого объекта, который выберет пользователь
В вашем случае для сохранения id
в session
требуется некоторый действие пользователя (чтобы выбрать какой).
Вам нужно будет отправить данные в params
и показать его в URL-адресе или отправить его в request body
метода POST
, требуя, чтобы вы использовали hidden_field
. Если вы не хотите, чтобы ваш id
был конфиденциальными данными Показать, вам необходимо создать обходной путь.
Я предлагаю вам использовать какой-нибудь метод шифрования для передачи ваших данных в параметрах, поскольку ваша основная проблема, похоже, заключается в том, что вы не хотите, чтобы идентификатор был видимым. Существует множество методов и библиотек шифрования, это только мое предлагаемое решение.
Я создал custom_route
, который будет получать encrypted_id
, поэтому вам не нужно записывать hidden_field
в форму.
get "/set_id/:encrypted_id" => "your_controller#set_encrypted_id", as: :set_id_route
И в представлении используйте custom_route
вместе с MessageEncryptor
следующим образом:
<% cookies[:salt] = SecureRandom.urlsafe_base64(32) %>
<% cookies[:pass] = 'some_password' %>
<% key = ActiveSupport::KeyGenerator.new(cookies[:pass]).generate_key(cookies[:salt], 32) %>
<% crypt = ActiveSupport::MessageEncryptor.new(key) %>
<% @owned_objects.each do |obj| %>
<%= form_for [obj, @wizard],
url: set_id_route(encrypted_id: crypt.encrypt_and_sign(obj.id)), # Or however you send the id
as: :wizard, method: :get do |f| %>
bla bla
<%= f.submit %>
<% end %>
<% end %>
Идентификатор будет отправлен в URL-адресе, но не будет читаться.
А затем в контроллере, на который вы хотите получить запрос, расшифруйте его и установите в session
.
def set_encrypted_id
key = ActiveSupport::KeyGenerator.new(cookies[:pass]).generate_key(cookies[:salt], 32)
crypt = ActiveSupport::MessageEncryptor.new(key)
session[:id] = crypt.decrypt_and_verify params[:encrypted_id]
render json: { session_id: 'ok' }
end
Я написал этот пример чтения и настройки cookies
, чтобы вы могли легко воспроизвести его, но они должны быть записаны в вашей базе данных или в переменных ENV
. В моем решении некоторые вещи не нужны, например, метод :get
или то, что encrypted_id
отправляется в параметрах URL (его можно отправить в request body
другого метода), но идея та же. Я надеюсь, что этот ответ будет вам полезен: если вам нужно взаимодействие с пользователем, вам нужно как-то сообщить об этом.
Вы хотите, чтобы все элементы были в одном сеансовом ключе или в отдельных ключах для каждого объекта?