user1486510
user1486510

Reputation: 139

Use of instance variables in controllers

Working through Rails Tutorial 3rd Edition by Michael Hartl: Ch 8 Log in, Log out

I need help understanding why in the session_controller we use a regular 'user' variable while in the users_controller we use an '@user' instance variable.

I noticed that in the session_controller, we use

def create
    user = User.find_by...

whereas in the users_controller, we use

 def create
   @user = User.new...

Michael states, "The main difference between the session form and the signup form is that we have no Session model, and hence no analogue for the @user variable..." referring to this:

form_for(@user)

from the users view versus

form_for(:session, url: login_path)

from the session view.

Is this related? I am still not understanding this. Please let me know if I need to be more clear or specific. Thank you!

Upvotes: 2

Views: 837

Answers (3)

Sharvy Ahmed
Sharvy Ahmed

Reputation: 7405

I am still not understanding this. Please let me know if I need to be more clear or specific.

Let's try to understand how all these things are working:

In users_controller, you are instantiating a blank user object by @user = User.new, which you will be using in your registration form. The reason of doing this is, if you instantiate a new object and pass that object as an argument in form, rails will automatically call create method of users_controller. Things will be done because of Rails RESTful resource route.

During #create,

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

is equivalent to:

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

On the other hand, if you instantiate an old record like @user = User.find(...), rails will call #update method of users_controller when you submit the form.

During #update,

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

is equivalent to:

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

So, now why instance variable is not used in sessions_controller #create action? Okay, if you instantiate an @user object and use that in login form like what you did in registration form, it will call #create action of users_controller instead of #create action of sessions_controller.

This is why in login form form_for(:session, url: login_path) is used. You will receive a Hash with :session key in it and since submitting url is explicitly told, that is login_path, the login information will submitted to #create action of sessions_controller.

Hope now things are making sense.

Upvotes: 0

djsmentya
djsmentya

Reputation: 315

Variables user and @user has different scopes

user variable available between words def end

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

you cannot use user variable outside the block of method definition, but if you use variable like @user you can

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

So only @user variable can be used in views. Author use local variable user in session_controller, because there no needs to use this variable in view and he use @user on users_controller because if user validation fails it will render form form_for(@user) with values that user entered before submit. So user do not have to fill all form fields again, he need just fix only wrong fields

Upvotes: 0

Prakash Murthy
Prakash Murthy

Reputation: 13067

def create
  user = User.find_by...

In this case, user is a local variable. It is just being used within the same method.

def create
  @user = User.new...

Here, @user is an instance variable, attached to the UsersController, and by making it an instance variable, it is made accessible in the corresponding views.

So if you look at any views related to users under app/views/users, there will be a reference to @user. Nothing of that sort is done in the views related to sessions (i.e. view files under app/views/sessions folder)

Upvotes: 0

Related Questions