在控制器中使用实例变量

时间:2015-03-12 21:20:44

标签: ruby-on-rails ruby session

通过Rails教程第3版由Michael Hartl完成:第8章登录,注销

我需要帮助理解为什么在session_controller中我们使用常规的'用户'在users_controller中我们使用' @ user'实例变量。

我注意到在session_controller中,我们使用

def create
    user = User.find_by...

而在users_controller中,我们使用

 def create
   @user = User.new...
迈克尔说,"会话形式和注册表单之间的主要区别在于我们没有会话模型,因此没有@user变量的模拟..."指的是:

form_for(@user)

来自用户视图与

form_for(:session, url: login_path)

来自会话视图。

这有关系吗?我仍然不理解这一点。如果我需要更清楚或更具体,请告诉我。谢谢!

3 个答案:

答案 0 :(得分:0)

def create
  user = User.find_by...

在这种情况下,user是一个局部变量。它只是在同一种方法中使用。

def create
  @user = User.new...

这里,@user是一个附加到UsersController的实例变量,通过使其成为实例变量,可以在相应的视图中访问它。

因此,如果您查看与app/views/users下的用户相关的任何观看次数,则会引用@user。在与会话相关的视图(即app/views/sessions文件夹下的视图文件)

中没有进行任何类似的操作

答案 1 :(得分:0)

变量user和@user具有不同的范围

单词def end之间可用的用户变量

def create
  user = User.new
  print user
end
create 
print user 
NameError: undefined local variable ...

你不能在方法定义块之外使用用户变量,但是如果你使用像@user这样的变量你可以

def create
  @user = User.new
  print @user
end
create 
print @user 
#<User:0x007fe1d25596d0>=> nil 

因此只能在视图中使用@user变量。 作者在session_controller中使用局部变量user,因为不需要在视图中使用此变量,并且他在users_controller上使用@user,因为如果用户验证失败,它将使用用户在提交之前输入的值呈现form_for(@user)格式。因此用户不必再次填写所有表单字段,他只需要修复错误的字段

答案 2 :(得分:0)

  

我仍然不理解这一点。如果我需要更清楚或更具体,请告诉我。

让我们试着了解所有这些事情是如何运作的:

users_controller中,您将@user = User.new实例化一个空白用户对象,您将在注册表单中使用该对象。这样做的原因是,如果您实例化一个新对象并将该对象作为参数传递给表单,rails将自动调用users_controller的create方法。由于Rails RESTful资源路由,事情将会完成。

#create期间,

<%= form_for(@user) do |f| %>
  ...
<% end %>

相当于:

<%= form_for @user, as: :user, url: users_path, html: { class: "new_user", id: "new_user" } do |f| %>
  ...
<% end %>

另一方面,如果您实例化@user = User.find(...)之类的旧记录,则当您提交表单时,rails会调用#update users_controller方法。

#update期间,

<%= form_for @user do |f| %>
  ...
<% end %>

相当于:

<%= form_for @user, as: :user, url: user_path(@user), method: :patch, html: { class: "edit_user", id: "edit_user_1" } do |f| %>
  ...
<% end %>

那么,现在为什么sessions_controller #create行动中没有使用实例变量?好的,如果您实例化@user对象并在登录表单中使用该对象,就像您在注册表单中所做的那样,它将调用#create users_controller的{​​{1}}行动,而不是#create sessions_controller

这就是使用登录表单form_for(:session, url: login_path)的原因。您将收到一个Hash,其中包含:session密钥,并且由于明确告知提交网址,即login_path,因此登录信息将提交至#create sessions_controller行为}}

希望现在事情变得有意义了。