Question about Helpers

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 is:

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 it appears that in most situations in rails, 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 use the methods in a certain controller you 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

...you can 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.

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 in the tests, 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. 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.

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.

A model class in rails is just a means for accessing a database. Rails automatically creates accessor methods for all the attributes/columns in your database. But you can always add setters and getters to a class, which is all a Model is, with attr_accessor or writing them out by hand. But when you add any extra setters and getters to a model, they won't correspond to any columns in the database--they are just programming, so using the setter won't save anything to the database, and using the getter won't retrieve anything from the database.

The methods in a model class are not 'actions' because rails doesn't map urls to them. 'Actions' are the methods inside a controller class. And rails maps urls to the actions, which is just a fancy way of saying that when your rails app receives a request from a browser, rails executes one of your actions. Which action rails executes when your app receives a browser request is determined by the url of the request and which action you tell rails to execute in response to that url in your routes.rb file.

But both models and controllers are just ruby classes, so attr_accessor can be used in both, and the rules about self are the same.

7stud -- wrote in post #1014079:

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.

It turns my get_user_from_cookie method created a branch of code not present in the book's code. Namely, in the book when @current_user is nil, then the right side of the || executes, and when that happens User.authenticate_with_salt gets called no matter what the cookke_array is equal to.

In my code, User.authenticate_with_salt doesn't get called if the cookie_array equals nil, and that creates a blind spot that the tests don't see.

To mimic the book's code, I changed my method to this:

def get_user_from_cookie

    @current_user || begin       cookie_array = cookies.signed[:remember_token] || [nil, nil]       @current_user = User.authenticate_with_salt(*cookie_arr) # a user or nil     end

  end