Question about Helpers

Studying the RoR 3 Tutorial book by Michael H.
and on page 345 there’s the code inside the SessionsHelper:


module SessionsHelper

def sign_in(user)
cookies.permanent.signed[:remember_token] = [user.id, user.sault]
self.current_user = user
end

end


What is the purpose of “self” inside the session helper?
I know that inside a model it refers to the class object.
For example

Class User < ActiveRecord::Base
self.salt

it refers to User.salt

But when it is inside a helper, does it refer to the helper itself?
sessions.current_user = user ?
What’s the meaning of it? To make it accessible to the controller &
view of Sessions ?

And also:

module SessionsHelper

def current_user= (user)
@current_user = user
end

The purpose of this line is to create an assignment to current user
and the existence of the instance variable @current_user is to
“permanently” stored, as long as it is needed (not as a local
variable) since there’s no model?

Im a little bit confused

Filippos wrote in post #1013927:

Studying the RoR 3 Tutorial book by Michael H.
and on page 345 there’s the code inside the SessionsHelper:


module SessionsHelper

def sign_in(user)
cookies.permanent.signed[:remember_token] = [user.id, user.sault]
self.current_user = user
end

end


What is the purpose of “self” inside the session helper?
I know that inside a model it refers to the class object.
For example

Class User < ActiveRecord::Base
self.salt

it refers to User.salt

But when it is inside a helper, does it refer to the helper itself?

Remember that no code inside a method actually executes until the method
is called. When the signin method is actually called by some object,
for instance:

some_object.sign_in(userA)

…then inside the sign_in() method, self is equal to the object that
called the sign_in method, which in this case is some_object.

However, the book never talks about what object is calling the various
methods. Instead, you have a controller like this:

class SessionsController < ApplicationController

def new
end

def create
end

def destroy
end

end

and the book talks about some url getting mapped to the new action, and
when that url is entered in a browser, the new action executes, and in
turn that causes rails to execute the file new.html.erb (and then rails
sends the resulting new.html file back to the browser). But if you know
any ruby, then you can infer that rails has to create a
SessionsController object, like this:

sess_controller = SessionsController.new

in order to be able to call the new, create, and destroy methods, e.g.

sess_controller.new

That part of the book confused me, too, because instead of this:

def sign_in

self.current_user = user
end

you could also write:

def sign_in

@current_user = user
end

but you definitely cannot write:

def sign_in

current_user = user
end

The last one creates a ‘local variable’ called current_user which will
be
destroyed when the sign_in method finishes executing. ‘@’ variables
persist as long as the sess_controller object still exists.

The way this code works:

def sign_in

self.current_user = user
end

is the self is the object calling the sign_in method. What object is
calling the sign_in method? That is a bit convoluted. The sign_in
method is in a module called SessionsHelpers, and you have this code in
a file:

class ApplicationController < ActionController::Base
protect_from_forgery
include SessionsHelper
end

That means all the methods in SessionsHelper become methods in the
ApplicationController class. But you also have this file:

class SessionsController < ApplicationController
def new
end

def create
end

def destroy
end

end

…so through inheritance all the ApplicationController methods become
methods of SessionsController–including the SessionsHelper methods. In
the end, that means a SessionsController object, e.g.

sess_controller = SessionsController.new

is the object that is going to be calling the sign_in method, and so
inside the sign_in method self is going to be equal to sess_controller.
Of course, rails calls sign_up behind the scenes, so what object is
calling sign_up isn’t obvious, and therefore determining what self is
inside the sign_up method isn’t obvious.

Now the question is why use self in the sign_in method here:

def sign_in

self.current_user = user
end

when you can avoid all that confusing stuff and just write:

def sign_in

@current_user = user
end

The answer is it’s good practice to always use an accessor method to
access an instance variable–rather than assign directly to an instance
variable. The reason is that if, for instance, you want to apply some
kind of transformation to a value before assigning it to an instance
variable, you can do that in the current_user=() method rather than
hunting through your code and looking for every line containing
@current_user = … ,
and making the change to each of those lines.

The purpose of this line is to create an assignment to current user
and the existence of the instance variable @current_user is to
“permanently” stored, as long as it is needed (not as a local
variable) since there’s no model?

@ variables can be seen in all the class’s methods (that is from ruby),
and in rails you have classes with names like SessionsController, and
the methods defined in the class are called actions. Rails arranges for
@ variables to be seen in any views as well.

In my previous post, I said:

‘@’ variables persist as long as the sess_controller object
still exists.

However, the web is a very ephemeral place to do business, i.e, things
exist for only a short period of time before being destroyed. For
instance, a browser sends a request to your rails app, which then
returns a response in the form of an html page, which usually happens in
few seconds–and then everything gets destroyed. Afterwards, the
browser doesn’t remember communicating with your rails app, and your
rails app doesn’t remember ever communicating with that browser.

As far as I know, because I am a rails beginner too (and I happen to be
at the same spot as you in the book), the sess_controller object, which
rails uses to call an action in response to a particular url, is
destroyed as soon as the application sends any html page back to the
browser.

The @current_user variable appears in this method:

def current_user=(user)
@current_user = user
end

And @ variables attach themselves to whatever is currently self, which
as discussed in my previous post will be this object:

sess_controller = SessionsController.new

So knowledge of the current user is destroyed when the sess_controller
object is destroyed, and that happens only a few seconds after the
browser
initially sends its request–hardly anything permanent.

The trick is to store a permanent cookie on the browser. When a browser
sends any request to your rails app, it adds all cookies that were
stored by your app. The code you are currently studying in the
book stores a cookie on the browser. Presumably, later in the book,
the
app will always check any browser request to see if the user is ‘signed
in’ or ‘signed out’, which means: did the browser send a ‘signed in’
cookie in the request, or was such a cookie absent. Also notice that is
why the methods are being added to a helper module, rather than being
defined directly in the SessionsController class: every page of your app
will have to check whether a signed in cookie is present in the
browser’s request.

The part that really confused me on p. 345 is where the
author says:

==
self.current_user = user

The purpose of this line is to create current_user, accessible in both
controllers and views which will allow constructions such as:

<%= current_user.name %>

and

redirect_to current_user

The author says “current_user” not 'the current_user function". He
refers to current_user as if it’s a variable. In addition, up to that
point
in the book we have been using @ variables in the view. So it seems
clear
to me that the real purpose of that line is to set the instance variable
@current_user, whose value can be retrieved with the ‘function’
current_user, or whose value can be set with the ‘function’
current_user=. I am quoting the word ‘function’ because in ruby, defs
are called methods–not functions.

It follows that the line:

<%= current_user.name %>

actually does this:

<%= current_user().name %>

However, the current_user function can be rewritten like this:

def current_user

#If for some reason @current_user already
#exists, return its value:

return @current_user if @current_user

#Check if the browser request contains a
#cookie named remember_token:

cookie_arr = cookies.signed[:remember_token]

if cookie_arr.nil?
return nil
else
return User.authenticate_with_salt(*cookie_arr)
end

end

But that function can return nil, so writing the following in the view:

<%= current_user.name %>

or writing this in an action:

redirect_to current_user

will cause errors if current_user is nil.

What I found to be a new concept in this section of the book is that we
can call methods in the view that are inherited by the
controller. In the book, the current_user method is inherited by the
controller like this:

SessionsHelper

def current_user

end

end

class ApplicationController < ActionController::Base

include SessionsHelper
end

class SessionsController < ApplicationController
def new
end

def create
end

def destroy
end

end

Interestingly, if you put the method directly in the controller, e.g.

class SessionsController < ApplicationController
def new
end

def create
end

def destroy
end

def current_user


end

end

…then rails will throw an error.


Something else I found very confusing was this on p. 348:

==
def current_user=(user)
@current_user = user
end

def current_user
@current_user
end



The problem is that it utterly fails to solve our problem: with the code
[above] the user’s sign in status would be forgotten: as soon as the
user went to another page–poof!–the session would end and the user
would be automatically signed out.

Huh? It’s my understanding that the created sess_controller object
which rails creates to call the methods defined in the
SessionsController
class; and which is
the repository for all the instance variables we define, like
@current_user, is going to go
poof! anyway. No code we write can prevent that.

The trick is to store the signed in status of the user in a cookie on
the browser before the sess_controller object goes poof!, and then every
time the browser makes another request for a page, we check to see if
the cookie named ‘remember_token’ gets added to the request (a browser
adds all cookies from our app to the request before sending the
request). If the cookie is present and contains the right information,
then we know the user is signed in; and if the cookie isn’t present,
then the user isn’t signed in.

So what I think the author is trying to say about this function:

def current_user
@current_user
end

is that the function will always return nil when the browser goes to
another page, so need to define it so that it checks for a cookie in the
browser request.

7stud – wrote in post #1013962:

The part that really confused me on p. 345 is where the
author says:

==
self.current_user = user

The purpose of this line is to create current_user, accessible in both
controllers and views which will allow constructions such as:

<%= current_user.name %>

and

redirect_to current_user

The author says “current_user” not 'the current_user function".

Actually, in the line:

self.current_user = user

the function being called is named ‘current_user=’. ruby syntax just
permits you to write it with a space before the equals sign.

It’s hard to tell if its just a typo when the author says
‘current_user’, and the author really means ‘@current_user’. Then there
is this final statement on the page:

==
The principal goal of this section is to define current_user.

A current_user getter method??! What’s that got to with the line:

self.current_user = user

I’m going to go with the following ‘translations’ (because it’s the only
way things make sense to me):

On page 345, this part:

===
self.current_user = user

The purpose of this line is to create current_user.

should say:

==
The purpose of this line is to to create @current_user.

And this introduction:

==
The principal goal of this section is to define current_user.

Should be clarified by saying:

==
The principal goal of this section is to define the current_user getter
function.

Also I said this:

Now the question is why use self in the sign_in method here:

def sign_in

self.current_user = user
end

when you can avoid all that confusing stuff and just write:

def sign_in

@current_user = user
end

The answer is it’s good practice to always use an accessor method to
access an instance variable–rather than assign directly to an instance
variable.

In that context, let’s look at the current_user function that the
author comes up with:

def current_user
@current_user ||= user_from_remember_token
end

I see two problems with that function. First off, that is a getter
function, yet it can set the @current_user variable. Getter functions
should not set instance variables. Secondly, the function directly sets
the @current_user variable instead of calling the current_user= setter
function.

Looking at the application code, i.e. the create action, nothing even
calls the current_user getter method. The create action calls the
sign_in helper method, but sign_in doesn’t call current_user. The only
thing that calls current_user is one of the tests. So we’re testing
something that the application code doesn’t even use???

In my opinion, the current_user getter method as defined in the book is
a complete disaster: breaking it up into three methods is confusing, a
getter method shouldn’t set an @ variable, and an @ variable should be
set indirectly by calling the @ variable’s setter method.

On Jul 31, 1:03pm, 7stud – [email protected] wrote:

It follows that the line:

<%= current_user.name %>

actually does this:

<%= current_user().name %>

Punctuation is usually optional in ruby when this doesn’t introduce
ambiguities.

What I found to be a new concept in this section of the book is that we
can
call methods in the view that are inherited by the
controller:

You can’t. The reason why the methods in SessionsHelper can be used in
the view is that (by default) all the helpers in app/helpers are
included in views.
When you add the method directly to the controller then this no longer
holds and so the view can’t find the method

Fred

I’m going to use these methods in my app instead of the current_user
method in the book:

#getter method:
def current_user
@current_user
end

#setter method:
def current_user=(user)
@current_user = user
end

def update_current_user
user = current_user #calls getter method
return user if user

cookie_arr = cookies.signed[:remember_token]

if cookie_arr
self.current_user = User.authenticate_with_salt(*cookie_arr)
#calls setter method

return current_user  #calls getter method

else
return nil
end

end

Any time the book calls current_user, I plan on calling
update_current_user instead.

For anyone that is still confused by the use of self in the following:

def some_method
self.current_user = …
end

You can just think to yourself @current_user = … Although, it really
calls the method:

def current_user(user)
@current_user = user
end

With that method definition, there is no difference between writing:

@current_user = …

and

self.current_user = …

But if you had something like this:

def current_user(user)
user.timestamp = Time.now
@current_user = user
end

Then writing the following in your code:

@current_user = …

would be different than writing:

self.current_user = …

The latter code would reset the timestamp attribute of user stored in
the @current_user variable.

Frederick C. wrote in post #1013993:

On Jul 31, 1:03pm, 7stud – [email protected] wrote:

It follows that the line:

<%= current_user.name %>

actually does this:

<%= current_user().name %>

Punctuation is usually optional in ruby when this doesn’t introduce
ambiguities.

What I found to be a new concept in this section of the book is that we
can
call methods in the view that are inherited by the
controller:

You can’t. The reason why the methods in SessionsHelper can be used in
the view is that (by default) all the helpers in app/helpers are
included in views.
When you add the method directly to the controller then this no longer
holds and so the view can’t find the method

Ahh. Okay.

What do you think about this:

def current_user
@current_user ||= user_from_remember_token
end

I see two problems with that function. First off, that is a getter
function, yet it can set the @current_user variable. Getter functions
should not set instance variables. Secondly, the function directly sets
the @current_user variable instead of calling the current_user= setter
function.

…and this solution:

#getter method:
def current_user
@current_user
end

#setter method:
def current_user=(user)
@current_user = user
end

def update_current_user
user = current_user #calls getter method
return user if user

cookie_arr = cookies.signed[:remember_token]

if cookie_arr
self.current_user = User.authenticate_with_salt(*cookie_arr)
#calls setter method

return current_user  #calls getter method

else
return nil
end

end

Although this is slicker:

def current_user=(user)
@current_user = user
end

def current_user
@current_user || get_user_from_cookie
end

def get_user_from_cookie
cookie_arr = cookies.signed[:remember_token]

if cookie_arr
user = User.authenticate_with_salt(*cookie_arr)
self.current_user = user #calls setter method
return user
else
return nil
end

end

…and then whenever the book calls current_user, you wouldn’t have to
change it.

Hmmm…but all I’ve really done is removed the code in the getter that
sets the instance variable into a function that the getter calls. That
still leaves me with a getter that sets the instance variable.

On Jul 31, 5:12pm, 7stud – [email protected] wrote:

the @current_user variable instead of calling the current_user= setter
function.

Memoization is an extremely common practice. I find the existence of
current_user= a little odd.

Fred

Frederick C. wrote in post #1014004:

On Jul 31, 5:12pm, 7stud – [email protected] wrote:

the @current_user variable instead of calling the current_user= setter
function.

Memoization is an extremely common practice. I find the existence of
current_user= a little odd.

Why’s that? In the SessionsHelper module there is a method that is
defined like this:

def signin(user)
cookies.permanent.signed[:remember_token] = [user.id, user.salt]
self.current_user = user
end

By the way, the book we are discussing is online and we are discussing
section 9.3:

http://ruby.railstutorial.org/chapters/sign-in-sign-out#sec:signin_success

On Jul 31, 6:17pm, 7stud – [email protected] wrote:

like this:

because you’ve got some weird halfway house where sometimes
current_user can work out what the current user is but in other cases
it’s assigned. Sometimes @current_user is just a cache, sometimes it’s
a most traditional ivar.

Fred

Ok, I’m not as advanced as 7stud. Im not familiar with ruby and I
started studying Rails.
Your replies where very informative but also a bit confusing at the
same time.

  1. So when we want to go to localhost/myapp/users/1 rails first maps
    the URL to Users#show, then creates the object user_controller =
    UsersController.new and then executes the user_controller.show?

  2. When we assign an instance variable inside the controller , doesn’t
    it refer to the controller object that rails create? For example @user
    -> user_controller = UsersController.new
    What would the difference be between the instance variable and the
    self.user inside t he controller method.

  3. I didn’t understand your justification of getter and setter.Since
    instance variables work fine why would you need to define a setter and
    getter. You can just assign to the instance variable and you’re done
    since it will be accessible in the controller and view for as long as
    the sess_controller lasts.

Instead of self.current_user = user we could write @current_user =
user

Why call the current_user getter and not just call the @current_user
directly.

I’m a bit confused.

The easy way would be to memorize or copy/paste but understanding the
code is better way to create rails apps.

On Jul 31, 7:41pm, Filippos [email protected] wrote:

Ok, I’m not as advanced as 7stud. Im not familiar with ruby and I
started studying Rails.
Your replies where very informative but also a bit confusing at the
same time.

  1. So when we want to go to localhost/myapp/users/1 rails first maps
    the URL to Users#show, then creates the object user_controller =
    UsersController.new and then executes the user_controller.show?

basically

  1. When we assign an instance variable inside the controller , doesn’t
    it refer to the controller object that rails create? For example @user
    → user_controller = UsersController.new
    What would the difference be between the instance variable and the
    self.user inside t he controller method.

I think you may be imagining magic that doesn’t exist.

directly.

For me the advantage of a current_user method over using @current_user
directly is that I don’t have to worry about whether I’ve setup
@current_user already or not, I can just call current_user and things
will not. Equally if I never need to check current_user then I don’t
do the work to set that up unnecessarily. That the current_user method
happens to cache its result in the instance variable of the same name
is just an implementation detail.

Fred

Filippos wrote in post #1014028:

  1. So when we want to go to localhost/myapp/users/1 rails first maps
    the URL to Users#show, then creates the object user_controller =
    UsersController.new and then executes the user_controller.show?

Yes.

  1. When we assign an instance variable inside the controller , doesn’t
    it refer to the controller object that rails create?

Yes. Instance variables attach themselves to an object–that object is
the object that calls the method in which the instance variable is set.
Here is an example:

class Dog
def bark
@color = “black”
puts “woof”
end

def color #getter method
@color
end
end

d = Dog.new
d.bark
puts d.color

–output:–
woof
black

For example @user
-> user_controller = UsersController.new
What would the difference be between the instance variable and the
self.user inside the controller method.

Lets see:

class Dog
def bark
@color = “black”
puts “woof”
end

def color
translate_to_german(@color)
end

def translate_to_german(word)
if word == “black”
‘schwartz’
else
‘not known’
end
end

def show
puts @color
puts self.color
end
end

d = Dog.new
d.bark
d.show

–output:–
woof
black #@color
schwartz #self.color

  1. I didn’t understand your justification of getter and setter.Since
    instance variables work fine why would you need to define a setter and
    getter.

Because it’s good programming practice.

You can just assign to the instance variable and you’re done
since it will be accessible in the controller and view for as long as
the sess_controller lasts.

Yes, but what if later you decide that you want to alter the value that
is assigned to the instance variable before doing the assignment? Then
you would have to look through your code and find every line where you
have written @var_name = …, and change it. What if your program was
10 million lines long? Would you want to do that? How long would it
take you? Two years? Twenty years?

If you always access instance variables using getters and setters, you
have the flexibility to change the value that is set or the value that
is retrieved. For instance suppose you were doing calculations in feet
and you decided you needed to do the calculations in meters. Without
changing the user interface, you could make those changes in the getter
and setter methods. The user could still enter the value in feet, and
then your
setter could convert to meters and save that value instead.

If you are interested in more examples, you can search google for
something like ‘why getters and setters’.

Instead of self.current_user = user we could write @current_user =
user

Why call the current_user getter and not just call the @current_user
directly.

I’m a bit confused.

The easy way would be to memorize or copy/paste but understanding the
code is better way to create rails apps.

  1. I didn’t understand your justification of getter and setter.Since
    instance variables work fine why would you need to define a setter and
    getter.

Because it’s good programming practice.

Ok, I took my own advice an read some articles about ‘why getter and
setters’ and there are enough people that think it’s actually bad
programming practice. They would recommend only having this method:

def get_user_from_cookie
@current_user || begin
cookie_array = cookies.signed[:remember_token]

if cookie_array
  @current_user = User.authenticate_with_salt(*cookie_arr)
  return @current_user
else
  return nil
end

end

end

…and not these methods:

def current_user=(user)
@current_user = user
end

def current_user
@current_user || …
end

But as far as I can tell the reasons I stated are
why the book is is using getters and setters.

wow thanx!

puts “woof”
‘not known’
end
end

def show
puts @color
puts self.color *
end
end

  • so in this context self.color calls the color method of the Dog
    class for the d object (d.color) . What if we omitted “self” , would
    rails execute the color method with the same result?

d = Dog.new
d.bark
d.show

–output:–
woof
black #@color
schwartz #self.color

If you are interested in more examples, you can search google for
something like ‘why
getters and setters’

Ok, i think i kind of understand what you mean here, but need some
examples. I will google it.
Getters and setters are the same with the attr_accessor but we can’t
use it in a controller because its an ActiveRecord attribute, right?

So inside the getter and setter we can define what is going to be
stored to or retrieved from an instant variable.

def online_user= (user)
@current_user = user
#or any other code we want to write
end

def online_user
@current_user

or any other code we want to write

end

Must the name of the “methods” (online_user) be the same with the
instant varialbe (@current_user) inside the “method” ?

Uggh. There must be a hole in my tests:

def get_user_from_cookie
@current_user || begin
cookie_array = cookies.signed[:remember_token]

  if cookie_array
    @current_user = User.authenticate_with_salt(*cookie_arr)
    return @current_user
  else
    return nil
  end

end # || block

end

*cookie_arr should be *cookie_array. But my tests didn’t throw an
error.

Filippos wrote in post #1014053:

wow thanx!

puts “woof”
‘not known’
end
end

def show
puts @color
puts self.color *
end
end

  • so in this context self.color calls the color method of the Dog
    class for the d object (d.color) . What if we omitted “self” , would
    rails execute the color method with the same result?

Yes, when a method is called without “a receiver”, i.e without an object
in front of it, then ruby calls the method with self. I explicitly
wrote self
so that it would be clearer what was going on. In fact, all
methods have to have a receiver, i.e an object that calls the method, so
if you don’t provide one, ruby uses self. One time when you do have to
explicitly write self is when you are on the left side of an equals
sign:

color = “black”

v.

self.color = “black”

In the first case, you create a local variable called color and assign
‘black’
to it. In the second case, you call the color=() method, which
typically sets
the @color variable to ‘black’.

d = Dog.new
d.bark
d.show

–output:–
woof
black #@color
schwartz #self.color

If you are interested in more examples, you can search google for
something like ‘why
getters and setters’

Ok, i think i kind of understand what you mean here, but need some
examples. I will google it.
Getters and setters are the same with the attr_accessor but we can’t
use it in a controller because its an ActiveRecord attribute, right?

Writing:

attr_accessor :color

is shorthand in ruby for this code:

def color=(val)
@color = val
end

def color
@color
end

You can call attr_accessor (yes it’s a method) in any class.

So inside the getter and setter we can define what is going to be
stored to or retrieved from an instant variable.

def online_user= (user)
@current_user = user
#or any other code we want to write
end

def online_user
@current_user

or any other code we want to write

end

Must the name of the “methods” (online_user) be the same with the
instant varialbe (@current_user) inside the “method” ?

The getter and setter method names will be the same as the instance
variable name if you use attr_accessor. If you write the methods by
hand, you can use different names, but that is not done. For
instance, you wouldn’t do this:

class Dog
def color=(val)
@age = val
end

def color
@age
end
end

d = Dog.new
d.color = 10
puts d.color

–output:–
10

I decided to try programming the app using the principles of the anti
getter/setter crowd. Those people say that instead of asking for a
value with
the getter, and then doing some calculation with the value, instead you
should
define a method in the class that does the calculation, and just call
that method. Then inside the method, you just set or get the @
variable
directly. Following those principles, here is what my SessionsHelper
module looks like:

module SessionsHelper

def sign_in(user)
cookies.permanent.signed[:remember_token] = [user.id, user.salt]
#self.current_user = user
@current_user = user
end

def signed_in?
get_user_from_cookie ? true : false
#I think that’s clearer than the double negative used in the book
end

def sign_out
cookies.delete(:remember_token)
@current_user = nil
end

def get_user_from_cookie
@current_user || begin
cookie_array = cookies.signed[:remember_token]

  if cookie_array
    @current_user = User.authenticate_with_salt(*cookie_arr)
    return @current_user
  else
    return nil
  end

end # || block

end

end

Then instead of calling current_user in the various actions, tests, and
helpers, I just call get_user_from_cookie. Note that wrapping several
lines of
code in a begin-end block tells ruby that the
result of the begin-end block is what goes on the right of the ||.

Filippos wrote in post #1014091:

your implementation makes more sense to me than the example of the
book.

In your code you write:

def get_user_from_cookie
@current_user || begin <------- what is the begin ? or is that line
code a typo?

The begin-end block allows you to write multiple lines of code on the
right side of an ||. It’s the same as if you did this:

@current_user || method_1

def method 1
cookie_array = cookies.signed[:remember_token]

  if cookie_array
    @current_user = User.authenticate_with_salt(*cookie_arr)
    return @current_user
  else
    return nil
  end

end

The return value of method1 gets inserted in place of the method1
‘function’ call on the right side of the ||.

Pffff… it took me back to basics!
According to the book with attr_accessor we create virtual attributes
(when we dont want to save something in the database).
But it uses them inside a model class (user class) so it’s been called
as self.password (when attr_accessor :password)
I didn’t see it outside a model class so im having problems
understanding and getting used to getter and setter outside a model
class since its the same thing.

All classes have the same abilities in ruby. It doesn’t matter whether
you call a class a Model or a Controller or something else.

Not to mention the “self” outside a model class… very strange.

self refers to different objects depending on where you are in your
code. The two main places that you need to know about are:

  1. Inside a class but outside any def’s, self refers to the class.
  2. Inside a method definition, self refers to the object calling the
    method. And in most situations in rails, it appears that is going
    to be the sess_controller = SessionsController.new object. Of course if
    you are inside a method in the UsersController, then rails will call
    those actions using a users_contr = UsersController.new object.

So the logic behind Helpers and the module is that when we’re not
using a model (px for Sessions) and since the code needed for sign-
in / sign-out doesn’t involve an action-view relationship like with
Controllers -it’s just methods and programming-

Apparently, rails allows you to put some methods into a common directory
when you want to use them in more than one controller. You put the
methods inside a module, and save the file in the app/helpers directory.
Then if you want to call the methods from an action inside a certain
controller,
you first write ‘include ModuleName’ in the application_controller.rb
file:

class ApplicationController < ActionController::Base
protect_from_forgery
include SessionsHelper
end

and that inserts the bundle of methods in the ApplicationController
class. And because your controllers all inherit from the
ApplicationController class:

class SessionsController < ApplicationController

#actions here

end

…you will be able to call any of the methods in the bundle from inside
the actions
in the SessionsController class.

About the methods.

def method1

end

is one type of method which doesn’t require an argument
whereas

def method2(string1, string2, string3…)

end

is the other type which requires input.

Yes. If you define a method to take no arguments, then you can’t call
it with any arguments:

class Dog
def bark
puts ‘woof’
end
end

d = Dog.new
puts d.bark(‘meow’)

–output:–
ruby.rb:2:in bark': wrong number of arguments (1 for 0) (ArgumentError) from ruby.rb:8:in

And if you define a method with one argument, you can’t call it with no
arguments or more than 1 argument:

class Dog
def bark(sound)
puts sound
end
end

d = Dog.new
puts d.bark(‘woof’, 10)

–output:–
ruby.rb:2:in bark': wrong number of arguments (2 for 1) (ArgumentError) from ruby.rb:8:in

So you mean that since we dont write “self” Rails infers:

self.method1 and self.method2(string1, string2, string3…) when we
call them?

Yes. All methods must be called by some object. If you don’t
explicitly write the object in front of the method call, then ruby uses
self.

with self being the session_controller = SessionsController.new or
session_helper = SessionsHelper.new?

Inside an action, self will be the object calling the action, which will
be the controller instance that rails creates to call the action. So
for a SessionsController action, rails will create a sess_controller =
SessionsController.new object, and for a UsersController rails will
create a users_contr = UsersController.new object. The only way you can
call methods in a class is if you first create an object of the class,
and then use that object to call the methods. A controller is just a
ruby class, and actions are just methods inside a class, so in order for
an action to execute, it has to be called using an object of that class.

The reason the tests did not catch the typo in my code is because the
create actions calls the signed_in helper method, and signed_in does
this:

@current_user = user

So when get_user_from_cookie is called:

def get_user_from_cookie
@current_user || begin …

@current_user is always true, so the right side of the || never
executes. That is true for the code in the book as well.
In other words, the tests we have written so far do not test
the case when @current_user = nil. I don’t know if that is an
oversight, or whether that will be tested later.