#ruby-on-rails #session
#ruby-on-rails #сеанс
Вопрос:
Предположим, это мой пользовательский контроллер:-
class UsersController < ApplicationController
def show
@user = session[:user]
end
def prepare
session[:user]= User.find(:first)
redirect_to :action => 'show'
end
def update
@user = session[:user]
@user.name = 'rai'
redirect_to :action => 'show'
end
end
Просмотр для show.html.erb
<%= @user.name %>
Show page
<%= link_to 'Update', :action=> 'update' %>
Теперь объясняю проблему:—
Предположим, что пользователь впервые открывает браузер с
http://localhost:3000/users/prepare
o / p будет:—
Mohit Show page Update // supposing user table has values mohit as name
Теперь, когда он нажмет на обновить, он получит в качестве вывода примерно следующее:—
rai Show page Update
Но этого не должно произойти, потому что
во-первых, когда выполняется действие подготовки, где значение извлекается из базы данных и ее мохита. и затем он перенаправляется на show ie, отображающий значения из сеанса. ie mohit
Теперь, когда пользователь нажимает на обновление, он перенаправляется на обновление, когда значение из сеанса сохраняется в экземпляре пользователя, и атрибут name этого экземпляра пользователя был изменен на rai. и, наконец, перенаправлен на страницу показа.
Теперь на этой странице, когда отображается имя пользователя, отображается rai .. вот ВОПРОС, почему?? потому что в сеансе должно храниться то же значение mohit, потому что мы не внесли никаких изменений в сеанс..
Ответ №1:
Когда вы делаете
@user = session[:user]
@user
переменной присваивается ссылка на объект session[:user]
, а не на его копию.
Итак, когда вы изменяете @user
, session[:user]
также изменяется, поскольку они, по сути, являются одним и тем же объектом.
Комментарии:
1. Да, вот что происходит.. я могу понять, но я не в состоянии понять, почему это происходит ..!!!
2. В ruby переменные содержат ссылки, а не значения. Итак, когда вы назначаете, вы копируете ссылки. ruby-doc.org/docs/Newcomers/ruby.html#objects
Ответ №2:
Я не уверен, но я думаю, что это что-то с хэшами и классами и с их копированием. Итак, когда вы делаете:
@user = session[:user]
Вы не создаете копию object, но это что-то вроде ссылки в C , оба @user
и session[:user]
ссылаются на один и тот же объект, поэтому, когда вы изменяете один, вы получаете оба изменения.
Пример из консоли:
a = {}
a[:user] = User.first
a[:user].firstname # => "Mohit"
b = a[:user]
b.firstname = 'rai'
a[:user].firstname # => 'rai'
a[:user] = User.first
a[:user].firstname # => 'Mohit'
Комментарии:
1. Да, вот что происходит.. я могу понять, но я не в состоянии понять, почему это происходит ..!!!
2. @piemesons: при назначении
@user = session[:user]
вы не копируете пользовательский объект. Вы копируете «указатель» на этот объект. Итак, например, если у вас есть друг по имени «Боб», и вы даете ему 100 долларов, то у него есть 100 долларов :). Теперь, если вы назовете его «Foo» (это тот же человек, но с другим именем) и дадите ему еще 100 долларов, у него теперь будет 200 долларов, а не 100 долларов. Это очень похоже на то, что произошло с вашим объектом сеанса.3. В этом примере консоли вы можете вызвать
a[:user].object_id
иb.object_id
, и это то же самое. Это означает, что обаa[:user]
иb
ссылаются на один и тот же объект.