Question about Helpers

Studying the RoR 3 Tutorial book by Michael Hartl
and on page 345 there's the code inside the SessionsHelper:

Filippos wrote in post #1013927:

Studying the RoR 3 Tutorial book by Michael Hartl
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,
which then 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

That 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 short answer: 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 @current_user = ... line
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.

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

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:

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.

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

Frederick Cheung wrote in post #1013993:

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:

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.

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

Fred

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.

Frederick Cheung wrote in post #1014004:

> 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 SessionsController 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

Frederick Cheung wrote in post #1014004:

>> > 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 SessionsController there is a method that is defined
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.

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

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.

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

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.

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.

2. 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 first
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

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.

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. Your getter
could then convert the value back to feet and return it.

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

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.

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. But as far as I can tell the reasons I stated are
why the book is is using getters and setters--however, the book does not
always use the getters and setters, so it is being consistent.

wow thanx!

> 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

* 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

> 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. Your getter
could then convert the value back to feet and return it.

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" ?

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. 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 and assign 'black' to it.
In the second case, you call the color=() method.

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?

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 is 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 could 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. They say that instead of asking for a value with
the getter, and then doing some calculation with the value, instead
define a method in the class that does the calculation, and just call
that method. 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
  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.

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.

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?

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.
Not to mention the "self" outside a model class... very strange.

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-
we use the SessionsHelper with modules and not the
ApplicationController.

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.

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

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

with self being the session_controller = SessionsController.new or
session_helper = SessionsHelper.new?
or is it any other object?