Ruby (and the Rails framework) is the first new programming language that I’ve learned since graduating with a CS degree way back in 1987; so, please bear with a virtual newbee on this question.
I’ve been working through Michael Hartl’s truly excellent tutorial, Learn Rails By Example. After making my way through the first 8 chapters relatively unscathed, I’ve hit a mental roadblock in Chapter 9. I understand the basic difference between instance variables and local variables (both in Ruby and more specifically in Rails). But, I do not understand why Michael uses the local variable “user” in his sessions controller rather than the instance variable “@user”. See, for example, the Create method in listing 9.9 of http://railstutorial.org/chapters/sign-in-sign-out#top .
Michael relies on a Sessions_helper module to make the following assignment: “@current_user = user”, but if he had used an instances variable in the first place, would he have needed to make the assignment at all (assuming that instances variables are available in controllers, views AND helpers)? Did he go with the local variable so that in the helper module he could redefine the “current_user” method to be,
def current_user
@current_user ||= user_from_remember_token
end
It’s probably clear to you guys that I’m floundering a bit here. Anyway, thanks in advance to anyone who can steer me straight.
-Chuck
First off, you don’t want to set an instance variable for
@userin regards to the session user, because it can clash with instance variable names in users_controller. Thats why authentication code opts for@current_user.Using the helper as a means to make these methods available to both the controller and view is a bit confusing to begin with. You are correct that he did this so the helper would set (or retrieve if already set) the
@current_user. Going with the Rails motto “skinny controllers, fat models” the writer does not want to define any of the authentication logic or authentication helpers within the controller, so he opts to use the helper to handle it. Also, if you set the@current_userin the create method it is pretty much useless because the rest of your app will not be able to use@current_user. Using theSessionHelperand including it in theApplicationControllerallows the rest of the app to use these methods in its controllers and views. In short, there is no need to make user an instance variable in the controller create method, because the SessionHelper sets the instance variable, which can be used in all controllers (because this was included in ApplicationController), and all the views (because it is in app/helpers).I opt for a different solution:
define a
before_filter(so it executes on every request) method in theApplicationControllerand include his code from the helper:then in the views instead of using
<% if signed_in? %>, I use<% if @current_user %>Using the before_filter executes this code on every request for every controller, while the tutorial method only calls the session code when any other part of the code calls
current_user, which you may prefer.My approach eliminates the need to put this stuff in
app/helpers/, which in my opinion should only be used for helping the views.. but hey, to each his own… I just find this approach easier to understand. The tutorial is very good and does an excellent job of separation in MVC and DRYness and there is no reason why you can’t use the method described in the tutorial.You may already know most of this, but I think the most important thing you can learn from this is that there should be very little business logic (aside from the routing logic) in the controller. The code in your controller should set instance variables (or call a method to set the session in this particular example) and route to the appropriate view. You can use models (or other modules) to do all the dirty work to create what should be in those instance variables. The controller and ApplicationController give you access to the http params and the session and you can pass the params to your fat models (since the models are not aware of params) and then your models should do the bulk of the work.