Hello, Why does it call send with a block which yields instead of just passing the block to send directly (like it used to)? # new way def method_missing(method, *args) if load_target if block_given? @target.send(method, *args) { |*block_args| yield(*block_args) } else @target.send(method, *args) end end end # old way def method_missing(method, *args) if load_target @target.send(method, *args, &block) end end This change messes up my implementation of full? which used to allow me to do stuff like this: puts self => #<Something:0x20e2c3c> post.author.full?{ puts self } # self inside that block will be that post''s author. => #<Author:0xc3c2e02> Now it''s like this... puts self => #<Something:0x20e2c3c> post.author.full?{ puts self } # self inside that block will be that post''s author. => #< Something:0x20e2c3c> I''m just curious why the change... and wondering if there is a way to make it compatible with my full? implementation so I won''t have to go refactor tons of code. Thanks for the help, -- Christopher --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
> I''m just curious why the change... and wondering if there is a way to > make it compatible with my full? implementation so I won''t have to go > refactor tons of code.The change was made to reduce the memory consumption and garbage generated when you have an explicit block parameter. However if it''s breaking things we can look at reverting it. It was *meant* to be fully backwards compatible. If you can add a test for what you''re doing, it''d make it easier for us to figure out the best way forward. -- Cheers Koz --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
Christopher J. Bottaro
2008-Sep-03 15:28 UTC
Re: AssociationProxy#method_missing now yields?
Here ya go... require "cases/helper" require ''models/post'' require ''models/author'' class Object def full? is_full = !blank? if is_full and block_given? instance_eval(&Proc.new) else is_full end end end class ProxySendTest < ActiveRecord::TestCase fixtures :authors, :posts def test_send self_is_author = nil post = Post.first post.author.full?{ self_is_author = self == post.author } assert self_is_author end end That test will pass with the old implementation of AssociationProxy#method_missing, but not the new. I do realize that that implementation of full? can lead to confusion and there is a good argument for it not to behave that way, but dang it, it makes for some pretty code sometimes... # dry a.very.long.assocation.chain.full?{ name } || "(no name)" page = params[:page].full?{ to_i } || 1 vs. # wet a.very.long.assocation.chain.full? ? a.very.long.assocation.chain.name : "(no name)" page = params[:page].full? ? params[:page].to_i : 1 -- C P.S. I think yall should put this implementation of #full? in Rails, as well as change #blank? to optionally take a block. :) On Sep 3, 2:45 am, "Michael Koziarski" <mich...@koziarski.com> wrote:> > I''m just curious why the change... and wondering if there is a way to > > make it compatible with my full? implementation so I won''t have to go > > refactor tons of code. > > The change was made to reduce the memory consumption and garbage > generated when you have an explicit block parameter. However if it''s > breaking things we can look at reverting it. It was *meant* to be > fully backwards compatible. > > If you can add a test for what you''re doing, it''d make it easier for > us to figure out the best way forward. > > -- > Cheers > > Koz--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
http://github.com/rails/rails/commit/13a60b83a470fb90f91a073b0540f7b02aa11ebd On Wed, Sep 3, 2008 at 11:28 AM, Christopher J. Bottaro <cjbottaro@gmail.com> wrote:> > Here ya go... > > require "cases/helper" > require ''models/post'' > require ''models/author'' > > class Object > def full? > is_full = !blank? > if is_full and block_given? > instance_eval(&Proc.new) > else > is_full > end > end > end > > class ProxySendTest < ActiveRecord::TestCase > fixtures :authors, :posts > > def test_send > self_is_author = nil > post = Post.first > post.author.full?{ self_is_author = self == post.author } > assert self_is_author > end > > end > > That test will pass with the old implementation of > AssociationProxy#method_missing, but not the new. > > I do realize that that implementation of full? can lead to confusion > and there is a good argument for it not to behave that way, but dang > it, it makes for some pretty code sometimes... > > # dry > a.very.long.assocation.chain.full?{ name } || "(no name)" > page = params[:page].full?{ to_i } || 1 > > vs. > > # wet > a.very.long.assocation.chain.full? ? > a.very.long.assocation.chain.name : "(no name)" > page = params[:page].full? ? params[:page].to_i : 1 > > -- C > > P.S. I think yall should put this implementation of #full? in Rails, > as well as change #blank? to optionally take a block. :) > > On Sep 3, 2:45 am, "Michael Koziarski" <mich...@koziarski.com> wrote: >> > I''m just curious why the change... and wondering if there is a way to >> > make it compatible with my full? implementation so I won''t have to go >> > refactor tons of code. >> >> The change was made to reduce the memory consumption and garbage >> generated when you have an explicit block parameter. However if it''s >> breaking things we can look at reverting it. It was *meant* to be >> fully backwards compatible. >> >> If you can add a test for what you''re doing, it''d make it easier for >> us to figure out the best way forward. >> >> -- >> Cheers >> >> Koz > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
> That test will pass with the old implementation of > AssociationProxy#method_missing, but not the new. > > I do realize that that implementation of full? can lead to confusion > and there is a good argument for it not to behave that way, but dang > it, it makes for some pretty code sometimes...The breakage is caused by the use of instance_eval in your full? method. The simplest fix for your code is to make it yield the object rather than relying on self being transformed: class Object def full? is_full = !blank? if is_full and block_given? yield self else is_full end end end params[:page].full? {|i| i.to_i} || 0 Alternatively you can monkeypatch the association proxy as well to avoid that method missing behaviour. I realise this isn''t ideal but to me relying on that instance_eval changing self is just too much of a corner case to be worth reverting the performance patch. -- Cheers Koz --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core+unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---