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? 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 -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
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. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
> 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. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
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: 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 uses to call the methods defined in the SessionsController class, including the inherited methods like current_user, is going to go poof! anyway, along with all its instance variables like @current_user. 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. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
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 = userI''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 came 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. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
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. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On Jul 31, 1:03 pm, 7stud -- <li...-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> 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 -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Frederick Cheung wrote in post #1013993:> On Jul 31, 1:03pm, 7stud -- <li...-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> 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 methodAhh. 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.-- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On Jul 31, 5:12 pm, 7stud -- <li...-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> > 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> -- > Posted viahttp://www.ruby-forum.com/.-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
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. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Frederick Cheung wrote in post #1014004:> On Jul 31, 5:12pm, 7stud -- <li...-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> 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 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 -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On Jul 31, 6:17 pm, 7stud -- <li...-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Frederick Cheung wrote in post #1014004: > > > On Jul 31, 5:12pm, 7stud -- <li...-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> 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 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> 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_su... > > -- > Posted viahttp://www.ruby-forum.com/.-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
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. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On Jul 31, 7:41 pm, Filippos <filippos...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> 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> 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> 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.-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
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''> 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.-- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
> 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. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
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" ? -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
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. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
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. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
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? -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
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. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
> 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. -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
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 -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Reasonably Related Threads
- before_save messing up
- Action Controller Error: undefined local variable or method `current_user'
- Questions about Chapter 9: Sign in, Sign out of RoR Tutorial | Learn Rails by Example
- NoMethodError in User sessionsController#new
- first app on Dreamhost with Passenger : "rails needs to know your username and password" ?