2

I have a has_many_polymorphs relationship between a Candidate and many events of various type. In particular, a Candidate creates a Created event when it is created.

class Candidate < ActiveRecord::Base
  has_many_polymorphs :events, :through => :candidate_events,
                               :from => Event::Base.included_in_classes.map { |klass|
                                 klass.to_s.underscore.pluralize.to_sym
                               })
  after_validation_on_create :create_created_event

  private
  def create_creation_event
    Event::Created.create!(:candidate => self, :creator => creator)
  end
end

class CandidateEvent < ActiveRecord::Base
  belongs_to :candidate
  belongs_to :event, :polymorphic => true
end

module Event::Base
  ...
end

class Event::Created < ActiveRecord::Base
  include Event::Base
  validates_presence_of :creator
end

When I run my unit tests, everything is fine. When I run my functional tests, everything is fine. When I run my integration (Cucumber) tests, everything is fine. When I run in production, everything is fine. When I try to run in development mode (with class-reloading on), I get

Referential integrity violation; child <Event::Created:1> was not found for :events.
Expected record['candidate_events.event_id'] (1) to be equal to record['created_events.id'] ().
  {
    "candidate_events.event_type"=>"Event::Created",
    "candidate_events.created_at"=>"2009-08-05 20:28:31",
    "candidate_events.updated_at"=>"2009-08-05 20:28:31",
    "candidate_events.candidate_id"=>"1",
    "candidate_events.event_id"=>"1",
    "candidate_events.id"=>"1"
  }

Running script/console in the same (development) environment I see that Event::Created object with the proper relationship to the CandidateEvent cross-reference model.

What's going on?

James A. Rosen
  • 64,193
  • 61
  • 179
  • 261
  • Can you show us the results of some sql queries for the relevant rows in those tables in your development database? – John Hyland Aug 05 '09 at 21:47
  • They're _really_ straightforward. I had only one row in each, and each had the proper foreign keys (all of which were "1") – James A. Rosen Aug 06 '09 at 11:51

1 Answers1

2

Can we be sure that Event::Base.included_in_classes is returning the right classes when classes reload? Isn't this trick sort of load order dependent? ie perhaps Event::Created hasn't yet included Event::Base?

jdwyah
  • 1,253
  • 1
  • 11
  • 22
  • Interesting question. I have some guard code set up to keep those classes from being defined twice because I was getting duplicate before_save hooks. I'll try putting the guards just around the hooks! – James A. Rosen Aug 06 '09 at 11:50
  • Hmm, that's not it. I've put `<% raise Event::Created.included_modules.inspect %>` at the top of the view causing the trouble and the result _does_ include `Event::Base` – James A. Rosen Aug 06 '09 at 12:12
  • I even threw a few "`require event`" lines around and put a "require event/created" (and all the others) at the bottom of event.rb. Still nothing. I'm still tempted by this line of thinking, though. – James A. Rosen Aug 06 '09 at 12:35
  • AHA! If I put a tracer statement ( puts "#{'=' * 40}\n#{Event::Base.included_in_classes.inspect}\n#{'=' * 40}") right after 'require event' at the top of candidate.rb I get "[]" as the result! – James A. Rosen Aug 06 '09 at 12:39
  • nice. you could also try some hot tapping action in the has_many_polymorphs. Event::Base.included_in_classes.tap{|c| p c}.map{|... I need to learn more about what class reloading really means. – jdwyah Aug 06 '09 at 16:57