Hey all, The Subject line may be a bad question, whether it''s possible to invoke a class method on an array of objects. But look at the code below, and unless I am misunderstanding, that''s what appears to be going on, and yes the code does work: class Dog def total_caught Cat.counters(:dog => self)[:caught] end class Cat def self.counters(constraints = {}) source = constraints[:dog] ? constraints[:dog].cats : self CatState.keys.map.each_with_object({}) { |k, h| h[k] source.count_of(k) end def self.count_of(state, options = {}) since = options.delete(:since) options[:conditions] = ["#{state}_on > ?", since] if since Cat.count("#{state}_on", options) end Basically, what''s going on here is when the total_caught method is invoked, it calls the Cat class method of Cat, passing into the argument list a hash key/value pair. We assign that hash to local variable constraints, and then check if the key dog exists, if so we get all associated cats to the dog. Hence, it is possible for the source local variable to hold an array of cat objects, which is the purpose of has_many and belongs_to. But then notice we call count_of which is a class method, so if source holds an array of objects, how is it possible to call the count_of class method of class Cat on it? thanks for response -- 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 19, 2011, at 4:18 PM, John Merlino wrote:> Hey all, > > The Subject line may be a bad question, whether it''s possible to > invoke a class method on an array of objects. But look at the code > below, and unless I am misunderstanding, that''s what appears to be > going on, and yes the code does work: > > class Dog > def total_caught > Cat.counters(:dog => self)[:caught] > end > > class Cat > def self.counters(constraints = {}) > source = constraints[:dog] ? constraints[:dog].cats : self > CatState.keys.map.each_with_object({}) { |k, h| h[k] > source.count_of(k) > end > > def self.count_of(state, options = {}) > since = options.delete(:since) > options[:conditions] = ["#{state}_on > ?", since] if since > > Cat.count("#{state}_on", options) > end > > Basically, what''s going on here is when the total_caught method is > invoked, it calls the Cat class method of Cat, passing into the > argument list a hash key/value pair. We assign that hash to local > variable constraints, and then check if the key dog exists, if so we > get all associated cats to the dog. Hence, it is possible for the > source local variable to hold an array of cat objects, which is the > purpose of has_many and belongs_to. But then notice we call count_of > which is a class method, so if source holds an array of objects, how > is it possible to call the count_of class method of class Cat on it? > > thanks for responseIf you have an array of objects, you can use map to pass a block to each member of that array, and the result will be an array holding the output of that block. [''foo'',''bar'',''baz''].map{|word| word.upcase } #-> [''FOO'',''BAR'',''BAZ''] So anything you want to put inside that block will work. If you need multiple lines, just use do and end instead of the curly braces. If you want to modify your objects in place, then I think you can use map! instead, and that will return the original array with each of its elements modified by the block. Walter> > -- > 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org > . > For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en > . >-- 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 19, 9:18 pm, John Merlino <stoici...-YDxpq3io04c@public.gmane.org> wrote:> Hey all, > > The Subject line may be a bad question, whether it''s possible to > invoke a class method on an array of objects. But look at the code > below, and unless I am misunderstanding, that''s what appears to be > going on, and yes the code does work: > > class Dog > def total_caught > Cat.counters(:dog => self)[:caught] > end > > class Cat > def self.counters(constraints = {}) > source = constraints[:dog] ? constraints[:dog].cats : self > CatState.keys.map.each_with_object({}) { |k, h| h[k] > source.count_of(k) > end > > def self.count_of(state, options = {}) > since = options.delete(:since) > options[:conditions] = ["#{state}_on > ?", since] if since > > Cat.count("#{state}_on", options) > end > > Basically, what''s going on here is when the total_caught method is > invoked, it calls the Cat class method of Cat, passing into the > argument list a hash key/value pair. We assign that hash to local > variable constraints, and then check if the key dog exists, if so we > get all associated cats to the dog. Hence, it is possible for the > source local variable to hold an array of cat objects, which is the > purpose of has_many and belongs_to. But then notice we call count_of > which is a class method, so if source holds an array of objects, how > is it possible to call the count_of class method of class Cat on it?Assuming these are active record objects and that dog has_many cats, then dog.cats isn''t actually an array, it''s an association proxy which will forwards attempts to call class methods of Cat onto Cat, setting the scope so that only the relevant cats will be found. If it was an actual array you wouldn''t be able to do this. Fred> > thanks for response-- 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.
Hi. Try to do something like this: CatState.keys.map.each_with_object({}) { |k, h| h[k] = source.to_a.inject(0){|sum, a| sum += count_of(a)} [1,2,3].inject(0) {|sum, a| sum += a } as result => 6 -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To view this discussion on the web visit https://groups.google.com/d/msg/rubyonrails-talk/-/SWHlO4BeABcJ. 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 19, 3:45 pm, Walter Lee Davis <wa...-HQgmohHLjDZWk0Htik3J/w@public.gmane.org> wrote:> > If you have an array of objects, you can use map to pass a block to > each member of that array, and the result will be an array holding the > output of that block. > > [''foo'',''bar'',''baz''].map{|word| word.upcase } #-> [''FOO'',''BAR'',''BAZ''] >Random note, you can use & and a symbol to send a message to each element in an array. So for the above example, it would be more concise to write [''foo'',''bar'',''baz''].map(&:upcase) #-> [''FOO'',''BAR'',''BAZ''] There are obviously still many times to use the block form, but I find a lot can be shortened to this and it makes the code more readable. \Peter -- 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.
Walter Lee Davis
2011-Jul-20 19:51 UTC
Re: Re: invoke a class method on an array of objects?
On Jul 20, 2011, at 11:00 AM, Peter wrote:> On Jul 19, 3:45 pm, Walter Lee Davis <wa...-HQgmohHLjDZWk0Htik3J/w@public.gmane.org> wrote: >> >> If you have an array of objects, you can use map to pass a block to >> each member of that array, and the result will be an array holding >> the >> output of that block. >> >> [''foo'',''bar'',''baz''].map{|word| word.upcase } #-> [''FOO'',''BAR'',''BAZ''] >> > > Random note, you can use & and a symbol to send a message to each > element in an array. So for the above example, it would be more > concise to write > > [''foo'',''bar'',''baz''].map(&:upcase) #-> [''FOO'',''BAR'',''BAZ''] > > There are obviously still many times to use the block form, but I find > a lot can be shortened to this and it makes the code more readable. >I agree. I was showing the block case in order to allow for more elaborate multi-step conversion. Walter> \Peter > > -- > 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-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org > . > For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en > . >-- 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.