class PaymentType < ActiveRecord::Base def self.get_payment_types payment_types_all = find(:all, :select => "display_name, stored_name" , :order => :display_name) # Creates a nested array of [[display_name, stored_name],[display_name, stored_name]] payment_types = payment_types_all.map {|item| [item.display_name, item.stored_name]} end # must be defined after the method. Can''t be defined in a method PAYMENT_TYPES = get_payment_types end Here is some code that works fine, but I don''t understand the need for the self reference in the def, I will get an undefined variable or method error. I don''t understand why I need the self when I am inside the class and I don''t understand if I need the self, why I can''t use self.get_payment_types Thanks -- Posted via http://www.ruby-forum.com/.
On Jul 13, 12:36 am, Buzz Hill <rails-mailing-l...-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:> class PaymentType < ActiveRecord::Base > > def self.get_payment_types > payment_types_all = find(:all, :select => "display_name, > stored_name" , :order => :display_name) > # Creates a nested array of [[display_name, > stored_name],[display_name, stored_name]] > payment_types = payment_types_all.map {|item| [item.display_name, > item.stored_name]} > end > > # must be defined after the method. Can''t be defined in a method > PAYMENT_TYPES = get_payment_types > > end > > Here is some code that works fine, but I don''t understand the need for > the self reference in the def, I will get an undefined variable or > method error. >in a nutshell def self.get_payment_types tells ruby to make a class method (which is basically a single method on the class object, ie self) rather than an instance method. Fred> I don''t understand why I need the self when I am inside the class and I > don''t understand if I need the self, why I can''t use > self.get_payment_types > > Thanks > -- > Posted viahttp://www.ruby-forum.com/.
In other words, you just use def get_payment_types if get_payment_types is to be performed on a specific instance of that class, and def self.get_payment_types if it is just a generic function for that class... E.g. def get_payment_types ... end pt = PaymentType.new pt_types = pt.get_payment_types -or- def self.get_payment_types ... end pt_types = PaymentType.get_payment_types On Jul 12, 7:40 pm, Frederick Cheung <frederick.che...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> On Jul 13, 12:36 am, Buzz Hill <rails-mailing-l...-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> > wrote: > > > > > class PaymentType < ActiveRecord::Base > > > def self.get_payment_types > > payment_types_all = find(:all, :select => "display_name, > > stored_name" , :order => :display_name) > > # Creates a nested array of [[display_name, > > stored_name],[display_name, stored_name]] > > payment_types = payment_types_all.map {|item| [item.display_name, > > item.stored_name]} > > end > > > # must be defined after the method. Can''t be defined in a method > > PAYMENT_TYPES = get_payment_types > > > end > > > Here is some code that works fine, but I don''t understand the need for > > the self reference in the def, I will get an undefined variable or > > method error. > > in a nutshell def self.get_payment_types tells ruby to make a class > method (which is basically a single method on the class object, ie > self) rather than an instance method. > > Fred > > > I don''t understand why I need the self when I am inside the class and I > > don''t understand if I need the self, why I can''t use > > self.get_payment_types > > > Thanks > > -- > > Posted viahttp://www.ruby-forum.com/. > >
JangoSteve wrote:> In other words, you just use def get_payment_types if > get_payment_types is to be performed on a specific instance of that > class, and def self.get_payment_types if it is just a generic function > for that class...I guess what I am confused about is this: Dave Thomas talks about self as a special variable used by Ruby to maintain a reference to the context of where the interpreter is operating and any given point, so it knows where to find a particular method. So why does Ruby not seem to know the context of "get_payment_types" without the self. Here is a slight variation on the previous code: class PaymentType def self.get_payment_types puts "Master Self is set to: " + self.to_s + " 1" puts payment_types = ["Check", "Credit Card", "Purchase Order"] end # must be defined after the method. Can''t be defined in a method PAYMENT_TYPES = get_payment_types p(PAYMENT_TYPES); puts puts "Master Self is set to: " + self.to_s + " 2" puts end puts "Master Self is set to: " + self.to_s + " 3" puts p(PaymentType::PAYMENT_TYPES << self.to_s) puts puts "Master Self is set to: " + self.to_s + " 4" This is an attempt to show the context contained in "self" at various points. You will see it change as the interpreter executes the code sequentially. As it executes in the class, Ruby understands the context. So, it knows it is in the class, so why can''t I call on a method without the self reference. When a call comes in from a browser, Rails starts executing inside a controller class, calling it''s methods who in turn call on each other within the same class, all of which typically won''t have the self reference. I am trying to get at some fundamental issue of object-oriented programming that I am don''t understand. -- Posted via http://www.ruby-forum.com/.
Hi -- On Mon, 13 Jul 2009, Buzz Hill wrote:> > JangoSteve wrote: >> In other words, you just use def get_payment_types if >> get_payment_types is to be performed on a specific instance of that >> class, and def self.get_payment_types if it is just a generic function >> for that class... > > I guess what I am confused about is this: > > Dave Thomas talks about self as a special variable used by Ruby to > maintain a reference to the context of where the interpreter is > operating and any given point, so it knows where to find a particular > method. So why does Ruby not seem to know the context of > "get_payment_types" without the self. Here is a slight variation on the > previous code:I think you''re confusing defining a method with calling a method. self always serves as the default receiver for messages -- meaning that this: my_method(a,b,c) is interpreted as this: self.my_method(a,b,c) When you''re defining a method, if you designate a specific object for the method, like this: def my_object.some_method(a,b,c) # ... end then the method will be a singleton method on that object -- meaning that the method is available only to that object. So when you do this: class Something def self.greet puts "Hello from #{self}!" end end you''re defining a method on the object self -- which happens to be, at that point in execution, the class object Something. There''s a bit more to it, but am I on the right track, in terms of what you''re finding confusing? David -- David A. Black / Ruby Power and Light, LLC Ruby/Rails consulting & training: http://www.rubypal.com Now available: The Well-Grounded Rubyist (http://manning.com/black2) Training! Intro to Ruby, with Black & Kastner, September 14-17 (More info: http://rubyurl.com/vmzN)
> So when you do this: > > class Something > def self.greet > puts "Hello from #{self}!" > end > end > > you''re defining a method on the object self -- which happens > to be, at that point in execution, the class object > Something.And just to beat the horse a little more, that is equivalent to writing: class Something def Something.greet puts "Hello from #{self]" end end In both cases you call the method on the class object itself (e.g., Something.greet). I''m not sure whether there are subtle differences between those two idioms--it seems like the self.greet formulation is more common (at least in the rails world). I think the other one is clearer, personally. GHC Confidentiality Statement This message and any attached files might contain confidential information protected by federal and state law. The information is intended only for the use of the individual(s) or entities originally named as addressees. The improper disclosure of such information may be subject to civil or criminal penalties. If this message reached you in error, please contact the sender and destroy this message. Disclosing, copying, forwarding, or distributing the information by unauthorized individuals or entities is strictly prohibited by law.
On Mon, Jul 13, 2009 at 6:28 AM, Buzz Hill<rails-mailing-list-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:> class PaymentType ># Inside a class definition self is the class itself # Note that another equivalent def statement would be # # def PaymentType.get_payment_types # # since PaymentTime also refers to the class itself.> def self.get_payment_types > puts "Master Self is set to: " + self.to_s + " 1" > puts > payment_types = ["Check", "Credit Card", "Purchase Order"] > end# Now let''s define an instance method def some_method # self here returns to the object which was sent some_method, it may refer to different objects at different times. # # self.get_payment_types # will fail here because self refers to an instance of PaymentType NOT the PaymentType class # # PaymentTypes.get_payment_types # will work, so would # self.class.get_payment_types end> # must be defined after the method. Can''t be defined in a method# Which I hope I just cleared up # # Now we are outside of the instance method definition, self once again refers to the class object # so this will invoke the class method.> > PAYMENT_TYPES = get_payment_types> end >-- Rick DeNatale Blog: http://talklikeaduck.denhaven2.com/ Twitter: http://twitter.com/RickDeNatale WWR: http://www.workingwithrails.com/person/9021-rick-denatale LinkedIn: http://www.linkedin.com/in/rickdenatale
To Everyone, Thanks for your help. When you are confused about something, it is sometimes hard to distill all your thoughts down to the essence of the issue and ask the right question. But I am trying to define a CONSTANT using the result of an instance method and Ruby just doesn''t allow that and I don''t understand why. Why does it have to be a class method? Is it because a constant is "class-only". It can''t be accessed by an instance. You could define an instance method that would return the same information as the constant but there is no syntax to access the constant directly from an instance object. So to define a constant, I can use a literal or a class method but not an instance method. And it can only be accessed via Class::Constant. Buzz -- Posted via http://www.ruby-forum.com/.
Buzz Hill wrote:> To Everyone, > > Thanks for your help. > > When you are confused about something, it is sometimes hard to distill > all your thoughts down to the essence of the issue and ask the right > question. But I am trying to define a CONSTANT using the result of an > instance methodNo you''re not. The constant you''re trying to define is clearly a class property. If you think about it, this is as it should be. The constant is going to have the same value for every instance of the class. In other words: a = PaymentType.new b = PaymentType.new a and b are now separate instances of PaymentType -- but surely you never want a.PAYMENT_TYPES to be different from b.PAYMENT_TYPES ?> and Ruby just doesn''t allow that and I don''t understand > why.It does allow it, but a "constant" that''s different for different instances is not really a constant and should probably not be represented as such. OTOH, if the constant is *not* different for different instances, then it should be a class property, not an instance property. Either way, you are asking for something that appears to have no utility whatsoever. Why bother?> > Why does it have to be a class method? Is it because a constant is > "class-only". It can''t be accessed by an instance. You could define an > instance method that would return the same information as the constant > but there is no syntax to access the constant directly from an instance > object.Sure there is: self.class::CONSTANT.> > So to define a constant, I can use a literal or a class method but not > an instance method.As I explained above, you can use an instance method, but there is no practical value to doing so.>And it can only be accessed via Class::Constant.> > BuzzBest, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org -- Posted via http://www.ruby-forum.com/.
Marnen Laibow-Koser wrote:>> >> When you are confused about something, it is sometimes hard to distill >> all your thoughts down to the essence of the issue and ask the right >> question. But I am trying to define a CONSTANT using the result of an >> instance method > > No you''re not. The constant you''re trying to define is clearly a class > property. > > If you think about it, this is as it should be. The constant is going > to have the same value for every instance of the class. In other words: > > a = PaymentType.new > b = PaymentType.new > > a and b are now separate instances of PaymentType -- but surely you > never want a.PAYMENT_TYPES to be different from b.PAYMENT_TYPES ? >The syntax of a.PAYMENT_TYPES won''t work. I am not sure if you meant it to work or you were just using it for the sake of explanation.>> and Ruby just doesn''t allow that and I don''t understand >> why. > > It does allow it, but a "constant" that''s different for different > instances is not really a constant and should probably not be > represented as such. OTOH, if the constant is *not* different for > different instances, then it should be a class property, not an instance > property. Either way, you are asking for something that appears to have > no utility whatsoever. Why bother? >Without trying to be arguementative, Ruby won''t allow this. class PaymentType def payment_types ["Check", "Credit Card", "Purchase Order"] end PAYMENT_TYPES = payment_types end This will error: NoMethodError But I get your point, which has enhanced my understanding. Things that relate to the class in general, things that shouldn''t be redefined, like Math:PI are controlled only by class methods. So, in the above example, if the payment_types were to change dynamically as the program executed, I would not use a constant, I would setup getter and setter methods.>> >> Why does it have to be a class method? Is it because a constant is >> "class-only". It can''t be accessed by an instance. You could define an >> instance method that would return the same information as the constant >> but there is no syntax to access the constant directly from an instance >> object. > > Sure there is: self.class::CONSTANT.Again, this syntax won''t work, if using self.payment_types pt = PaymentType.new pt.PaymentType::PAYMENT_TYPES Error: NoMethodError: undefined method ‘PaymentType’> >> >> So to define a constant, I can use a literal or a class method but not >> an instance method. > > As I explained above, you can use an instance method, but there is no > practical value to doing so.See above.> >> > And it can only be accessed via Class::Constant. >> >> Buzz > > Best, > -- > Marnen Laibow-Koser > http://www.marnen.org > marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org-- Posted via http://www.ruby-forum.com/.
Buzz Hill wrote: [...]> The syntax of a.PAYMENT_TYPES won''t work. I am not sure if you meant it > to work or you were just using it for the sake of explanation.I meant "assuming proper definition such that it *would* work, how would you want it to behave?". It''s possible to get it to work, just unnecessary. [...]> Without trying to be arguementative, Ruby won''t allow this. > > class PaymentType > > def payment_typesThis syntax defines an instance method.> ["Check", "Credit Card", "Purchase Order"] > end > > PAYMENT_TYPES = payment_typesThis syntax calls a class method, since we''re outside of any method definition here.> > end > > This will error: NoMethodErrorRight. You''re defining an instance method, then trying to call a class method that you haven''t defined. For this to work, you''d need to do PAYMENT_TYPES = @some_instance.payment_types.> > But I get your point, which has enhanced my understanding. Things that > relate to the class in general, things that shouldn''t be redefined, like > Math:PI are controlled only by class methods.Sort of. I was more trying to say that while you could set up instance constants, there is no point.> So, in the above example, > if the payment_types were to change dynamically as the program executed, > I would not use a constant, I would setup getter and setter methods.It''s not so much about changing dynamically as it is about whether the property conceptually belongs to the class or the instance. Do you understand the difference between class and instance attributes? It sounds like you don''t, or else this would all be clear to you. [...]>> Sure there is: self.class::CONSTANT. > > Again, this syntax won''t work, if using self.payment_types > > pt = PaymentType.new > pt.PaymentType::PAYMENT_TYPES > > Error: NoMethodError: undefined method ‘PaymentType’Yes. That''s not what I said. I said pt.class::PAYMENT_TYPES, which will absolutely work. pt.PaymentType will look for an instance method called PaymentType, which you haven''t defined. Best, -- Marnen Laibow-Koser http://www.marnen.org marnen-sbuyVjPbboAdnm+yROfE0A@public.gmane.org -- Posted via http://www.ruby-forum.com/.
Hi -- On Tue, 14 Jul 2009, Buzz Hill wrote:> Marnen Laibow-Koser wrote: > >>> >>> When you are confused about something, it is sometimes hard to distill >>> all your thoughts down to the essence of the issue and ask the right >>> question. But I am trying to define a CONSTANT using the result of an >>> instance method >> >> No you''re not. The constant you''re trying to define is clearly a class >> property. >> >> If you think about it, this is as it should be. The constant is going >> to have the same value for every instance of the class. In other words: >> >> a = PaymentType.new >> b = PaymentType.new >> >> a and b are now separate instances of PaymentType -- but surely you >> never want a.PAYMENT_TYPES to be different from b.PAYMENT_TYPES ? >> > > The syntax of a.PAYMENT_TYPES won''t work. I am not sure if you meant it > to work or you were just using it for the sake of explanation.The syntax will work if you''ve got an instance method called PAYMENT_TYPES, but if you don''t, it will fail -- whether or not you have a constant called PAYMENT_TYPES.> But I get your point, which has enhanced my understanding. Things that > relate to the class in general, things that shouldn''t be redefined, like > Math:PI are controlled only by class methods. So, in the above example, > if the payment_types were to change dynamically as the program executed, > I would not use a constant, I would setup getter and setter methods.I think you''re overthinking it. There''s no inherent connection between constants and class methods. module MyMathModule PI = 3.14159265358979 end puts "PI is #{MyMathModule::PI}" I''ve created a module and a constant inside that module. The constant is resolved using the :: operator, and no methods are involved. If you define an instance method, you can use the class''s constants: class Rainbow COLORS = %w{ red orange yellow green blue indigo violet } def show_me_the_colors puts "My colors are: #{COLORS.join(", ")}" end end r = Rainbow.new r.show_me_the_colors => My colors are: red, orange, yellow, green, blue, indigo, violet David -- David A. Black / Ruby Power and Light, LLC Ruby/Rails consulting & training: http://www.rubypal.com Now available: The Well-Grounded Rubyist (http://manning.com/black2) Training! Intro to Ruby, with Black & Kastner, September 14-17 (More info: http://rubyurl.com/vmzN)
On Tue, Jul 14, 2009 at 8:46 AM, David A. Black<dblack-0o/XNnkTkwhBDgjK7y7TUQ@public.gmane.org> wrote:>> I think you''re overthinking it. There''s no inherent connection between > constants and class methods. > > module MyMathModule > PI = 3.14159265358979 > end > > puts "PI is #{MyMathModule::PI}" > > I''ve created a module and a constant inside that module. The constant > is resolved using the :: operator, and no methods are involved. > > If you define an instance method, you can use the class''s constants: > > class Rainbow > COLORS = %w{ red orange yellow green blue indigo violet } > > def show_me_the_colors > puts "My colors are: #{COLORS.join(", ")}" > end > end > > r = Rainbow.new > r.show_me_the_colors > > => My colors are: red, orange, yellow, green, blue, indigo, violetI was going to say that defining a class constant like this, initialized by an expression evaluated when the class definition is executed is normally the way to go. But then I went back an looked at the post at the beginning of this thread, and looked at the code, which when rewritten to look something like this: def self.get_payment_types payment_types_all = find(:all, :select => "display_name, stored_name" , :order => :display_name) payment_types = payment_types_all.map {|item| [item.display_name, item.stored_name]} end # must be defined after the method. Can''t be defined in a method PAYMENT_TYPES = find(:all, :select => "display_name, stored_name" , :order => :display_name)..map {|item| [item.display_name, item.stored_name]} And note that since we are really getting the payment types from the database, a constant might not be the right path. If the payment types can change over time, then it''s not a constant. If it is a constant maybe the database isn''t the best place to save it. -- Rick DeNatale Blog: http://talklikeaduck.denhaven2.com/ Twitter: http://twitter.com/RickDeNatale WWR: http://www.workingwithrails.com/person/9021-rick-denatale LinkedIn: http://www.linkedin.com/in/rickdenatale
Thanks again to everyone for your help. I keep reading over this thread and appreciating the things being explained to me. I have gained a better understanding of the separation of class things and instance things. I just need to keep studying. Buzz -- Posted via http://www.ruby-forum.com/.
On Tue, 14 Jul 2009, Rick DeNatale wrote:> > On Tue, Jul 14, 2009 at 8:46 AM, David A. Black<dblack-0o/XNnkTkwhBDgjK7y7TUQ@public.gmane.org> wrote: >> > >> I think you''re overthinking it. There''s no inherent connection between >> constants and class methods. >> >> module MyMathModule >> PI = 3.14159265358979 >> end >> >> puts "PI is #{MyMathModule::PI}" >> >> I''ve created a module and a constant inside that module. The constant >> is resolved using the :: operator, and no methods are involved. >> >> If you define an instance method, you can use the class''s constants: >> >> class Rainbow >> COLORS = %w{ red orange yellow green blue indigo violet } >> >> def show_me_the_colors >> puts "My colors are: #{COLORS.join(", ")}" >> end >> end >> >> r = Rainbow.new >> r.show_me_the_colors >> >> => My colors are: red, orange, yellow, green, blue, indigo, violet > > I was going to say that defining a class constant like this, > initialized by an expression evaluated when the class definition is > executed is normally the way to go. > > But then I went back an looked at the post at the beginning of this > thread, and looked at the code, which when rewritten to look something > like this:I was addressing myself at this point to the general matter of constant scope, visibility, and syntax, which I think was an impediment to analyzing the underlying problem. David -- David A. Black / Ruby Power and Light, LLC Ruby/Rails consulting & training: http://www.rubypal.com Now available: The Well-Grounded Rubyist (http://manning.com/black2) Training! Intro to Ruby, with Black & Kastner, September 14-17 (More info: http://rubyurl.com/vmzN)