0

I'm making a system to generate pub quizzes for pubs. To ensure that a pub doesn't receive the same quiz twice, pubs and quizzes have a many to many association.

class Quiz < ActiveRecord::Base
  has_and_belongs_to_many :pubs
  serialize :rounds, Array
  before_create :generate_rounds

  def generate_rounds
    # Round class initializes with array of pubs
    NUMBER_OF_ROUNDS.times { rounds << Round.new(pubs: self.pubs) }
  end 
end

class Pub < ActiveRecord::Base
  has_and_belongs_to_many :quizzes
end

A quiz has rounds (an array of Round objects that contain questions) that are serialized using the ActiveRecord method serialize.

When I run this code:

q = Quiz.new
q.pubs << Pub.create
q.save

I got:

ArgumentError: undefined class/module HABTM_Pubs

Previously, I had a belongs_to relation (a quiz belonged to one pub) and this error didn't occur.

When I comment out the before_create callback (so rounds don't get created), the q.save action succeeds.

From my schema.rb

create_table "pubs_quizzes", id: false, force: true do |t|
  t.integer "pub_id"
  t.integer "quiz_id"
end

Things like Quiz.new.pubs work.

Edit: the stack trace

from /home/geert/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/psych/class_loader.rb:53:in `path2class'
from /home/geert/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/psych/class_loader.rb:53:in `resolve'
from /home/geert/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/psych/class_loader.rb:45:in `find'
from /home/geert/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/psych/class_loader.rb:27:in `load'
from /home/geert/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/psych/visitors/to_ruby.rb:360:in `resolve_class'
from /home/geert/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/psych/visitors/to_ruby.rb:87:in `deserialize'
from /home/geert/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/psych/visitors/to_ruby.rb:122:in `visit_Psych_Nodes_Scalar'
from /home/geert/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/psych/visitors/visitor.rb:15:in `visit'
from /home/geert/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/psych/visitors/visitor.rb:5:in `accept'
from /home/geert/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/psych/visitors/to_ruby.rb:31:in `accept'
from /home/geert/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/psych/visitors/to_ruby.rb:302:in `block in revive_hash'
from /home/geert/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/psych/visitors/to_ruby.rb:300:in `each'
from /home/geert/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/psych/visitors/to_ruby.rb:300:in `each_slice'
from /home/geert/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/psych/visitors/to_ruby.rb:300:in `revive_hash'
from /home/geert/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/psych/visitors/to_ruby.rb:161:in `visit_Psych_Nodes_Mapping'
from /home/geert/.rvm/rubies/ruby-2.1.2/lib/ruby/2.1.0/psych/visitors/visitor.rb:15:in `visit'

It must have something to do with serialization.

Relevant item? YAML::load raises undefined class/module error

Community
  • 1
  • 1
Kappie001
  • 898
  • 2
  • 10
  • 20

1 Answers1

1

Serializing an array with objects that reference an ActiveRecord association seems to cause the error.

replacing

Round.new(pubs: self.pubs)

with

Round.new(pub_ids: self.pubs.map { |pub| pub.id })

and fetching the pubs in the Round class itself makes the error go away.

Kappie001
  • 898
  • 2
  • 10
  • 20