Ruby 1.8.4 rc breaks alias_method/rails in bad ways


#1

i’m on a box with latest (today’s) ruby and rails. i started seeing
bizzare
errors with infinite stack recursion for a simple

ModelName.find :all

the code is kinda deep, but you can see how the problem occurs by
looking at

activerecord-1.13.1/lib/active_record/callbacks.rb +215

there we see

object = instantiate_without_callbacks(record)

scanning up a bit we see

 def self.append_features(base) #:nodoc:
   super

   base.extend(ClassMethods)
   base.class_eval do
     class << self
       include Observable
       alias_method :instantiate_without_callbacks, :instantiate
       alias_method :instantiate, :instantiate_with_callbacks
     end

the first alias method is supposed to do

instantiate_without_callbacks -> ActiveRecord::Base::instaniate

the second

instantiate -> the yet to be defined
ActiveRecord::Callbacks::instantiate_with_callbacks

which takes you back to line 215, shows:

 module ClassMethods #:nodoc:
   def instantiate_with_callbacks(record)

··· ect = instantiate_without_callbacks(record)

what is supposed to happen here is that any call to
ActiveRecord::Base::instantiate first calls instantiate_with_callbacks,
which
calls instantiate_without_callbacks, which calls the, supposedly,
original
ActiveRecord::Base::instantiate.

what actually happens in this:

Company.find :all

/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.13.1/lib/active_record/base.rb:431:in
`find_by_sql’

/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.13.1/lib/active_record/base.rb:431:in
`find_by_sql’

/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.13.1/lib/active_record/base.rb:395:in
`find’

  • (irb):1:in `irb_binding’

  • /usr/local/lib/ruby/1.8/irb/workspace.rb:52:in `irb_binding’

  • /usr/local/lib/ruby/1.8/irb/workspace.rb:52

/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.13.1/lib/active_record/callbacks.rb:222:in
`instantiate’

/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.13.1/lib/active_record/base.rb:431:in
`find_by_sql’

/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.13.1/lib/active_record/base.rb:431:in
`find_by_sql’

/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.13.1/lib/active_record/base.rb:395:in
`find’

  • (irb):1:in `irb_binding’

  • /usr/local/lib/ruby/1.8/irb/workspace.rb:52:in `irb_binding’

  • /usr/local/lib/ruby/1.8/irb/workspace.rb:52

/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.13.1/lib/active_record/callbacks.rb:222:in
`instantiate’

/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.13.1/lib/active_record/base.rb:431:in
`find_by_sql’

/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.13.1/lib/active_record/base.rb:431:in
`find_by_sql’

/usr/local/lib/ruby/gems/1.8/gems/activerecord-1.13.1/lib/active_record/base.rb:395:in
`find’

  • (irb):1:in `irb_binding’
  • /usr/local/lib/ruby/1.8/irb/workspace.rb:52:in `irb_binding’
  • /usr/local/lib/ruby/1.8/irb/workspace.rb:52

and so on and so forth. eg. - infinite recursion.

it seems the original instanciate is lost in this whole method shuffling
approach.

this code works in 1.8.2 and 1.8.3. unless the bevhaiour of
alias_methods has
changed - hard to beleive - this seems to be a bad bug. i’ve tried to
distill
this to a simple example with no luck. so i’m afaid there is more to
it that
the above. all you need do to reproduce is setup a rails dir, create a
model,
and run YourModel.find :all.

system info

root:rr# uname -srm
FreeBSD 5.3-RELEASE i386

root:rr# ruby -v
ruby 1.8.4 (2005-12-01) [i386-freebsd5.3]

root:rr# rails -v
Rails 0.14.4

hopefully i’ve not overlooked something obvious here - our water pipes
froze
today so i haven’t been able to drink coffee.

thoughts?

-a

===============================================================================
| ara [dot] t [dot] howard [at] noaa [dot] gov
| all happiness comes from the desire for others to be happy. all misery
| comes from the desire for oneself to be happy.
| – bodhicaryavatara


#2

On Sat, 10 Dec 2005, Ara.T.Howard wrote:

quick follow up. tweaking activerecord/base.rb to

def __instantiate(record)

and activerecord/callbacks.rb to

def instantiate_without_callbacks(record)·
__instantiate(record)
end
def instantiate(record)
instantiate_with_callbacks(record)
end
def instantiate_with_callbacks(record)
object = instantiate_without_callbacks(record)

while deleting the aliases works - so the issue is defintely in
alias_methods
or rails’ use of it.

-a

===============================================================================
| ara [dot] t [dot] howard [at] noaa [dot] gov
| all happiness comes from the desire for others to be happy. all misery
| comes from the desire for oneself to be happy.
| – bodhicaryavatara


#3

I just got done compiling 1.8.4 preview 2 (not the daily) on cygwin,
windows xp sp2, edge rails 3275.
no errors, no warnings during the compile of ruby and
all ext libs/programs.

i ran your ‘find(:all)’ test and everything works properly
on my configuration.

the problem you are experiencing happened to me a couple
of months ago when i was running 1.8.2. It went away but
I can’t remember exactly how i made it go away; i was
either doing something boneheaded or i rebooted/restarted/reinstalled
something.

i too was surprised to see this recursive behavior but since
i’m still so new to ruby i wrote it off as “ruby magic,” and
sure enough the problem went away after messing with
my configuration/code.


#4

On Sun, 11 Dec 2005, Michael S. wrote:

On Friday 09 December 2005 21:06, Ara.T.Howard wrote:

i’m on a box with latest (today’s) ruby and rails. i started seeing
bizzare errors with infinite stack recursion for a simple

Does this problem occur in the production envrionment or only in development
environment? I’ve experienced infinite recursions numerous times and they’ve
always been related to the reloading that’s happening in the development
environment.

both. check the ruby-core mailing list for the fix i figured out…
basically
i just reworked a few lines that changed the alias_method stuff going on
and
it’s fine (though this is hardly confidence inspiring). it’s clearly
something pretty deep happening that’s unrelated to which env it’s run
under.

regards.

-a

===============================================================================
| ara [dot] t [dot] howard [at] noaa [dot] gov
| all happiness comes from the desire for others to be happy. all misery
| comes from the desire for oneself to be happy.
| – bodhicaryavatara


#5

Hi,

At Sat, 10 Dec 2005 05:07:00 +0900,
Ara.T.Howard wrote in [ruby-core:06864]:

it seems the original instanciate is lost in this whole method shuffling
approach.

this code works in 1.8.2 and 1.8.3. unless the bevhaiour of alias_methods has
changed - hard to beleive - this seems to be a bad bug. i’ve tried to distill
this to a simple example with no luck. so i’m afaid there is more to it that
the above. all you need do to reproduce is setup a rails dir, create a model,
and run YourModel.find :all.

Don’t you have simpler script which can reproduce it?


#6

On Friday 09 December 2005 21:06, Ara.T.Howard wrote:

i’m on a box with latest (today’s) ruby and rails. i started seeing
bizzare errors with infinite stack recursion for a simple

Does this problem occur in the production envrionment or only in
development environment? I’ve experienced infinite recursions numerous
times and they’ve always been related to the reloading that’s happening
in the development environment.

Michael


Michael S. The Fifth Rider of the Apocalypse
mailto:removed_email_address@domain.invalid is a programmer.
http://www.schuerig.de/michael/