Can someone explain why you can''t use the return value of an ActiveRecord::Base collection in a case() statement properly? Here''s an example:>> item = User.find_by_username(''me'').books[#<Book:0xb771b4b0 ... snip>> case item; when Array then ''this is an array''; else "not an array, but a(n) #{item.class}"; end=> "not an array, but a(n) Array">> item === Array=> true Can someone explain what''s going on here? I''m baffled. The workaround I''ve come up with is to insert item = item.to_a if item === Array before the case statement, but that''s sooo hacky. --~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@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 -~----------~----~----~----~------~----~------~--~---
Xavier Noria
2006-Oct-09 08:25 UTC
Re: What collection type does the has_many macro create?
On Oct 9, 2006, at 9:43 AM, eden li wrote:> Can someone explain what''s going on here? I''m baffled. The > workaround > I''ve come up with is to insert > > item = item.to_a if item === Array > > before the case statement, but that''s sooo hacky.Indeed, has_many and friends do not return an Array, they return a subclass of ActiveRecord::Associations::AssociationCollection defined in active_record/associations/association_collection.rb -- fxn --~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@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 -~----------~----~----~----~------~----~------~--~---
What sort of magic is going on to have it return Array as its class then? I''m still baffled about the following console output:>> item.class=> Array>> item === Array=> true Xavier Noria wrote:> Indeed, has_many and friends do not return an Array, they return a > subclass of > ActiveRecord::Associations::AssociationCollection > defined in > active_record/associations/association_collection.rb--~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@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 -~----------~----~----~----~------~----~------~--~---
Xavier Noria
2006-Oct-09 12:32 UTC
Re: What collection type does the has_many macro create?
On Oct 9, 2006, at 10:34 AM, eden li wrote:> What sort of magic is going on to have it return Array as its class > then? I''m still baffled about the following console output: > >>> item.class > => Array >>> item === Array > => trueI got something, ActiveRecord::Associations::AssociationProxy redefines === and defines def method_missing(method, *args, &block) load_target @target.send(method, *args, &block) end I traced method_missing is called whenever object.assoc.class is called and delegates the call to @target, which is a true Array. That explains partially what we see, but I fail to understand why is method_missing called at all with a method inherited from Object. -- fxn --~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@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 -~----------~----~----~----~------~----~------~--~---
Xavier Noria wrote:> I got something, ActiveRecord::Associations::AssociationProxy > redefines === and defines > > ..snip..Ah, I didn''t think to look one class up. That explains it.> ... I fail to understand why is method_missing called at all > with a method inherited from Object.I''m guessing it''s this line (#7 of association_proxy.rb in rails 1.1.6): instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?|^proxy_respond_to\?|^proxy_extend|^send)/ } --~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@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 -~----------~----~----~----~------~----~------~--~---
Xavier Noria
2006-Oct-09 12:51 UTC
Re: What collection type does the has_many macro create?
On Oct 9, 2006, at 2:32 PM, Xavier Noria wrote:> On Oct 9, 2006, at 10:34 AM, eden li wrote: > >> What sort of magic is going on to have it return Array as its class >> then? I''m still baffled about the following console output: >> >>>> item.class >> => Array >>>> item === Array >> => true > > I got something, ActiveRecord::Associations::AssociationProxy > redefines === and defines > > def method_missing(method, *args, &block) > load_target > @target.send(method, *args, &block) > end > > I traced method_missing is called whenever object.assoc.class is > called and delegates the call to @target, which is a true Array. That > explains partially what we see, but I fail to understand why is > method_missing called at all with a method inherited from Object.Oh yes, there''s this at the top of that class instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil \?|^proxy_respond_to\?|^proxy_extend|^send)/ } which effectively removes Object#class and thus method_missing is triggered. We are getting closer, but not yet explaining that === fails to match Array in the case statement. -- fxn --~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@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 -~----------~----~----~----~------~----~------~--~---
It looks like Ruby doesn''t even use the === operator in the case() statement: irb(main):005:0> class C; def ===(k); puts "called=== with #{k.inspect}";true; end; end => nil irb(main):006:0> case C.new; when String; ''string''; else; ''not''; end => "not" irb(main):007:0> C.new===String called=== with String => true Maybe this question is ready to be ported over to ruby-talk. Xavier Noria wrote:> We are getting closer, but not yet explaining that === fails to match > Array in the case statement.--~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@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 -~----------~----~----~----~------~----~------~--~---
Gareth Adams
2006-Oct-09 13:14 UTC
Re: What collection type does the has_many macro create?
eden li <eden.li@...> writes:> > Xavier Noria wrote: > > I got something, ActiveRecord::Associations::AssociationProxy > > redefines === and defines > > > > ..snip.. >It''s also useful to understand that a === b often isn''t the same as b === a irb(main):001:0> 1 === Fixnum => false irb(main):002:0> Fixnum === 1 => true case 1; when Fixnum; end # Will actually compare Fixnum === 1 --~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@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 -~----------~----~----~----~------~----~------~--~---
Xavier Noria
2006-Oct-09 13:24 UTC
Re: What collection type does the has_many macro create?
On Oct 9, 2006, at 3:09 PM, eden li wrote:> It looks like Ruby doesn''t even use the === operator in the case() > statement: > > irb(main):005:0> class C; def ===(k); puts "called=== with > #{k.inspect}";true; end; end > => nil > irb(main):006:0> case C.new; when String; ''string''; else; ''not''; end > => "not" > irb(main):007:0> C.new===String > called=== with String > => true > > Maybe this question is ready to be ported over to ruby-talk.Great! --~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@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 -~----------~----~----~----~------~----~------~--~---
Ah, that''s it. So AssociationProxy won''t ever be able to intercept the === call in the case/when, thus never allowing it to match the "when Array" statement. That clears it up... Gareth Adams wrote:> case 1; when Fixnum; end # Will actually compare Fixnum === 1--~--~---------~--~----~------------~-------~--~----~ 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-/JYPxA39Uh5TLH3MbocFFw@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 -~----------~----~----~----~------~----~------~--~---