Reputation: 8054
In Ruby 1.8.6, I could write class PerformableMethod < Struct.new(:object, :method, :args)
Now in Ruby 1.9.3, that throws an error: superclass mismatch for class PerformableMethod
It works if I change the code to:
class PerformableMethod
attr_accessor :object, :method_name, :args
But why doesn't the struct work?
Upvotes: 1
Views: 424
Reputation: 8066
The class name is optional also in 1.9 and 2.0. The problem is this:
> Struct.new(:asdf, :qwer) == Struct.new(:asdf, :qwer)
=> false
Even if you provide a class name for your Struct
:
> Struct.new("Zxcv", :asdf, :qwer) == Struct.new("Zxcv", :asdf, :qwer)
(irb):22: warning: redefining constant Struct::Zxcv
=> false
This means that if you have this in a file that you load or require:
class MyClass < Struct.new(:qwer, :asdf)
def some_method
puts "blah"
end
end
... then if you load it again -- maybe because you changed something and you want to try it without restarting irb, or maybe you are running Rails in dev mode and it reloads classes on each request -- then you get the exception:
TypeError: superclass mismatch for class MyClass
... because every time your class definition runs, it is declaring a brand new Struct
as the superclass of MyClass
. Providing a class name to Struct.new()
does not help, as seen in the second code block; That just adds a warning about redefining a constant, and then opening the class fails anyway.
The only way to avoid the exception is to stash your Struct
in a constant somewhere you control and make sure not to change that constant when the file is reloaded.
Upvotes: 5
Reputation: 8054
While typing out this question, my colleague sitting right next to me figured it out.
Struct now takes the class name as its first parameter.
So in Ruby 1.9.3 the following works:
class << Struct.new('PerformableMethod', :object, :method, :args)
Upvotes: 0