【问题标题】:Use of instance variables in controllers在控制器中使用实例变量
【发布时间】:2015-03-14 16:18:18
【问题描述】:

Michael Hartl 编写的通过 Rails 教程第 3 版工作:第 8 章登录、注销

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

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

def create
    user = User.find_by...

而在 users_controller 中,我们使用

 def create
   @user = User.new...

Michael 指出,“会话表单和注册表单之间的主要区别在于我们没有会话模型,因此没有 @user 变量的类似物......”指的是:

form_for(@user)

从用户角度对比

form_for(:session, url: login_path)

从会话视图。

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

【问题讨论】:

    标签: ruby-on-rails ruby session


    【解决方案1】:
    def create
      user = User.find_by...
    

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

    def create
      @user = User.new...
    

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

    因此,如果您在app/views/users 下查看与用户相关的任何视图,则会有对@user 的引用。在与会话相关的视图中没有进行任何此类操作(即查看app/views/sessions 文件夹下的文件)

    【讨论】:

      【解决方案2】:

      变量 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)。所以用户不必再次填写所有表单字段,他只需要修复错误的字段

      【讨论】:

        【解决方案3】:

        我还是不明白。如果我需要更清楚或更具体,请告诉我。

        让我们试着了解所有这些东西是如何工作的:

        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会在你提交表单时调用users_controller#update方法。

        #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 对象并在登录表单中使用它,就像您在注册表中所做的那样,它将调用users_controller#create 操作而不是sessions_controller#create 操作。

        这就是在登录表单中使用form_for(:session, url: login_path) 的原因。您将收到一个带有:session 密钥的Hash,并且由于明确告知提交网址,即login_path,登录信息将提交给#createsessions_controller 的操作。

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

        【讨论】:

        • “那么,现在为什么在 session_controller #create 操作中不使用实例变量?好的,如果你实例化一个 @user 对象并在登录表单中使用它,就像你在注册表单中所做的那样,它将调用 users_controller 的 #create 动作而不是 session_controller 的 #create 动作。”
        • 你是说在 UsersController 中定义的 @user 实例变量在 views/users/ 之外的表单中可用?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多