ActiveRecord Unexplainable SystemStackError - Only in WEBrick

This SystemStackError is driving me crazy. It only takes place when testing with WEBrick - I can't reproduce it with any tests. It is caused by calling the "missing" id method (base.rb:2435) on my ActiveRecord class.

WEBrick and my tests are running as the same user, with a `ulimit -s` of 10240. Plus the query works sometimes so I don't think this matters.

Here's the trace:

/usr/lib/ruby/1.8/set.rb:93:in `empty?' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ attribute_methods.rb:64:in `generated_methods?' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ attribute_methods.rb:237:in `method_missing' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ attribute_methods.rb:245:in `method_missing' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ base.rb:2435:in `hash' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ association_preload.rb:13:in `uniq' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ association_preload.rb:13:in `preload_associations' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ base.rb:1343:in `find_every' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ base.rb:536:in `find' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ association_preload.rb:254:in `find_associated_records' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ association_preload.rb:154:in `preload_has_many_association' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ association_preload.rb:40:in `send' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ association_preload.rb:40:in `preload_one_association' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ association_preload.rb:38:in `each' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ association_preload.rb:38:in `preload_one_association' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ association_preload.rb:17:in `preload_associations' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ association_preload.rb:16:in `preload_associations' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ association_preload.rb:16:in `each' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ association_preload.rb:16:in `preload_associations' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ base.rb:1343:in `find_every' /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ base.rb:536:in `find' app/models/package.rb:29:in `search'

The thing is, sometimes it works -at first. And usually results in the trace ending before Set.empty? at: /usr/lib/ruby/gems/1.8/gems/activerecord-2.1.0/lib/active_record/ attribute_methods.rb:64:in

Here's the relevant parts of my code:

class Package < ActiveRecord::Base   has_many :deliveries, #,:select=>'id, user, host, delivered, region_id, package_id',                   :include=>:region,                   :dependent=>:delete_all

def self.search(criteria)    raise ArgumentError, 'argument must be of type SearchCriteria' unless criteria.is_a\ ?(SearchCriteria)     clause = build_search_where_clause(criteria)     find(:all, :include=>[:deliveries], :conditions=>clause) end end

class Delivery < ActiveRecord::Base   belongs_to :package   belongs_to :region end

class Region < ActiveRecord::Base   has_many :deliveries end

Looking at the SQL output, the exception is occurring after the :deliveries relation is queried. At first I though it was because I left out the id field from the has_many :deliveries, :select=>'...' But I commented it out and still no luck.

Any suggestions/ideas are greatly appreciated.

Overkill. The searching is rudimentary so I just quickly created something.

In any case, I take it you had no thoughts as to why I'm receiving the stack error -other than possibly implying it was because of the SearchCriteria class?

Why not use a search plugin like thinking sphinx to do your searching for you?

Overkill. The searching is rudimentary so I just quickly created something.

In any case, I take it you had no thoughts as to why I'm receiving the stack error -other than possibly implying it was because of the SearchCriteria class?

Does it only happen when class caches is false ?

Fred

Why yes Fredrick, it does. I wonder why that can be. Your thoughts would be appreciated.

Regardless, you have provided me with a new area to look into.

Thanks!

> Does it only happen when class caches is false ?

Why yes Fredrick, it does. I wonder why that can be. Your thoughts would be appreciated.

That pretty much means that the automated reloading is bollocksed. For example this can happen if rails clears out a class you were still using or something like that. It can be quite hard to pinpoint what exactly the problem is. Areas to look out for are using require when you should use require_dependency and associations between models in your app and models in plugins

Fred

So how is the conditions clause built. can you log it before passing it to find?

Al

OK, I understand this require_dependency thing but in my case I don't see how this applies. I thought that this code, in my lib dir, might be the cause:

require 'activerecord' class Validator < ActiveRecord::Base   def self.columns     @columns ||= ;   end   #snip ... end

require 'validator' class SearchCriteria < Validator #snip attribs end

But, the source of my pain, this call:

Package.search(criteria)

executes:

SHOW FIELDS FROM `packages`   Delivery Load (0.000409) SELECT `deliveries`.* FROM `deliveries` WHERE (`deliveries`.package_id IN (319089123))   Delivery Columns (0.000961) SHOW FIELDS FROM `deliveries`   Region Load (0.000370) SELECT * FROM `regions` WHERE (`regions`.id IN ('4803144','5750247'))

when the Delivery class is being assembled by ActiveRecord - SystemStackError

This has nothing to do with the above classes and or require_dependency... I think.

class Package < ActiveRecord::Base   has_many :deliveries, #,:select=>'id, user, host, delivered, region_id, package_id',                   :include=>:region,                   :dependent=>:delete_all

def self.search(criteria)     raise ArgumentError, 'argument must be of type SearchCriteria' unless criteria.is_a?(SearchCriteria)     clause = build_search_where_clause(criteria)     find(:all, :include=>[:deliveries], :conditions=>clause) end

def self.build_search_where_clause(criteria)    where =    [:region,:date,:status].each do |prop|    case prop       when :region          where << send(:sanitize_sql, [ 'deliveries.region_id in (?)', value ])       #snip clauses    end    where.join(' and ') end

class Delivery < ActiveRecord::Base   belongs_to :package   belongs_to :region end

class Region < ActiveRecord::Base   has_many :deliveries end

I'm at a loss -still.

Thanks for your help.

Yes I can see the clause in the development log. The query is valid, it executes fine. It's when the Delivery class is assembled by ActiveRecord that the stack exception occurs, Well, only when the action is processed by WEBrick.

Package.search(criteria)

executes:

SHOW FIELDS FROM `packages` Delivery Load (0.000409) SELECT `deliveries`.* FROM `deliveries` WHERE (`deliveries`.package_id IN (319089123)) Delivery Columns (0.000961) SHOW FIELDS FROM `deliveries` Region Load (0.000370) SELECT * FROM `regions` WHERE (`regions`.id IN ('4803144','5750247'))

when the Delivery class is being assembled by ActiveRecord - SystemStackError

This has nothing to do with the above classes and or require_dependency... I think.

It could for example be problematic if the parent class of
SearchCriteria isn't being reloaded by SearchCriteria is. Assuming
these things are all in appropriate files you don't need that "require
'validator'" at all.

Fred