Question

I have a problem where the dynamic finders used in my Ruby on Rails application almost always work, but very rarely a NoMethodError will be thrown.

Here is a copy of the exception stack from when things do go wrong:

2013-10-16 05:34:04.723 [Rails/26343   ] :
NoMethodError (undefined method `find_by_id' for #<Class:0xa972ef8>):
  app/models/sas_ui/supergroup_instance.rb:394:in `event_by_id'
  app/models/trace.rb:73:in `event_by_id'
  app/controllers/tview_controller.rb:102:in `select_event'
  lib/tview_logging_control.rb:22:in `call'

The code which causes the exception to be thrown (supergroup_instance line 394):

event = SasUi::Event.find_by_id(event_db_id)

SasUi::Event is a subclass of SasUi, which is a subclass of ActiveRecord::Base.

Here is the database entry:

                                         Table "public.events"

   Column   |            Type             |                      Modifiers
------------+-----------------------------+---------------------------------------
 id         | integer                     | not null default nextval('events_id_seq'::regclass)
 sg_inst_id | integer                     | not null
 sas_id     | integer                     | not null
 system_id  | integer                     |
 trail_id   | bigint                      |
 event_id   | integer                     |
 time       | timestamp without time zone |
 sqn        | bigint                      |
 instance   | integer                     |
 data       | bytea                       |
Indexes:
    "events_pkey" PRIMARY KEY, btree (id)
    "index_events_on_sg_inst_id" btree (sg_inst_id)
Foreign-key constraints:
    "events_sg_inst_id_fk" FOREIGN KEY (sg_inst_id) REFERENCES supergroup_instances(id) ON DELETE CASCADE

This works 99.99% of the time, we have a few hundred customers using this software, but very occasionally, one customer sees this problem. Logging out of the application and back in seems to resolve the problem.

There are multiple threads in the application accessing these models, which is another possible avenue to explore.

As I understand it, dynamic finders work by overriding the method missing method, and splitting the name of the called method on the _ character to extract the requested attribute names. If the extracted attributes exist in attribute_names in the model, then the query will be made, otherwise the original NoMethodError will be thrown.

attribute_names has the following documentation:

Returns an array of column names as strings if it’s not an abstract class and table exists. Otherwise it returns an empty array.

There are no suggestive entries in the postgres logs or application logs, except for the exception listed above.

My initial thoughts are that there may be some intermittent database problem, where for some reason postgres reports that the table doesn't exist. Restarting the app does not restart the database, but does resolve the problem.

I wondered if it could alternatively be down to rails caching tables, and that cache somehow being corrupted.

Has anyone seen this before or know what could cause this to happen? Alternatively, any suggestions on any further diagnosis steps would be appreciated.

I know these finders are deprecated in more recent releases, but moving on to a new version is not an option for this release of software, and I'd like to get to the bottom of this, in case it indicates some deeper problems.

Here are the software versions / platform:

 - Rails: 3.0.20
 - Ruby: 1.9.2p180
 - Postgres: 9.0.3
 - SunOS <blanked-out> 5.10 Generic_137138-09 i86pc i386 i86pc

Adding a bit more information, in case the cause is related to autoload:

SasUi::Event - class declaration: class SasUi::Event < SasUi
SasUi::Event - class location on disk: ../app/models/sas_ui/event.rb

There are two other events classes:
Data::Event - class declaration: class Data::Event < ActiveRecord::Base
Data::Event - class location on disk: ../app/models/data/event.rb

Event - class declaration: class Event < DelegateClass(SasUi::Event)
Event - class location on disk: ../app/models/event.rb

No correct solution

OTHER TIPS

Use modules as namespaces, not classes.

What you have done (class under class) is called inner class and should not be reached outside upper class.

Nested classes question.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top