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 -~----------~----~----~----~------~----~------~--~---