Superclass mismatch, Struct, reloading and Spork
Asked Answered
R

4

6

Suppose there's the following class

# derp.rb
class Derp < Struct.new :id
end

When I load "./derp.rb" twice the program fails with TypeError: superclass mismatch for class Derp. Ok, this could be managed with require. But how can I reload such classes for each test run with Spork? require obviously won't work cause it caches the loaded files.

Ruysdael answered 20/3, 2012 at 11:14 Comment(0)
D
6

Struct.new is creating new class for your every load.

irb(main):001:0> class Test1 < Struct.new :id; end
nil
irb(main):003:0> class Test1 < Struct.new :id; end
TypeError: superclass mismatch for class Test1
    from (irb):3
    from /usr/bin/irb:12:in `<main>'

You can save your Struct.new returned class to a variable and you can use that will be always the same class.

irb(main):004:0> Id = Struct.new :id
#<Class:0x00000002c35b20>
irb(main):005:0> class Test2 < Id; end
nil
irb(main):006:0> class Test2 < Id; end
nil

or You can use Struct.new block style instead of class keyword it will only give warning: already initialized constant Test3 when you reload your file.

irb(main):023:0> Test3 = Struct.new(:id) do
                     def my_methods
                     "this is a method"
                     end
                   end
Disadvantaged answered 20/3, 2012 at 12:51 Comment(2)
I see. But this won't help me with Spork: creating constants for each kind of Struct kinda defeats the purposeRuysdael
@Ruysdael Struct.new is always returning new class. maybe you can split same type of methods (can be created with accessors) to modules and include them.Disadvantaged
R
3

You can make sure the struct class is created only once.

Test1 < $test1 ||= Struct.new(:id)

Regurgitate answered 2/8, 2013 at 16:11 Comment(1)
This works but will cause warnings. Like this warning: already initialized constant WebCalendarHelper::MonthCalendar::HEADERLubricant
R
1

For those finding this on Google, this is what solved it for me:

module MyModule
  class MyClass
    MyClassStruct ||= Struct.new(:id)
    SomeStruct < MyClassStruct
    ...
  end
end
Rainbolt answered 7/4, 2017 at 23:49 Comment(0)
P
0

Thanks to @dignoe. Their solution work for me when trying to eager loading:

class D::Potencia < Struct.new(:potencia_instalada)
end

That gave me SuperClass MisMatch on rspec test.

Failure/Error: class D::Potencia < Struct.new(:potencia_instalada)

TypeError: superclass mismatch for class Potencia

Now we can perform test on all code base before publishing to production.

module D
  ClasePotenciaInstalada ||= Struct.new(:potencia_instalada)
  class D::Potencia < ClasePotenciaInstalada
  end
end
Photoflood answered 3/7, 2022 at 7:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.