Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

chef/knife (ruby) error: superclass mismatch for class Edit (TypeError)

i am using bundler to handle ruby gems dependencies. i require the gems using bundler programatically.

when i try to invoke knife programatically, which its dependency is specified within the Gemfile i get en error. i execute knife as follows:

Chef::Knife.run ["-v"] #invoking knife

and it returns the following error:

/var/lib/gems/2.0.0/gems/chef-11.6.2/lib/chef/knife/edit.rb:5:in `<class:Knife>': superclass mismatch for class Edit (TypeError)

i am familiar with Ruby on Rails 3 : "superclass mismatch for class ..." and the reason this occurs. but there is nothing i do which coincide with the explanation within the aforementioned stackoverflow post.

can somebody shed the light on the issue and a resolution for it?

like image 996
Mr. Avatar asked Mar 22 '23 09:03

Mr.


1 Answers

You are right, that's the related error.

class Edit was already defined somewhere else with a different superclass from the one is trying to use now.

Simple test on irb/pry

[56] pry(main)> class Comida; end

[57] pry(main)> class Comida < Integer; end

TypeError: superclass mismatch for class Comida
from (pry):53:in `__pry__'

So you should post/check what exactly are you requiring with bundler programatically and how. Why not use a Gemfile and then bundle exec to run your script? Let bundler handle dependencies for you, if you did this programatically because you are concerned on how and when are the gems required you can add required: false to avoid the automatic behavior and do yourself the requires when needed, i.e.

Change this Gemfile

gem 'chef-solo'
gem 'knife-solo'

To this:

gem 'chef-solo', require: false
gem 'knife-solo', require: false

Then manually in your code perform the requires when you fit necessary and take back the control you needed:

# ... code ....
require 'chef-solo'

# ... more code ...
require 'knife-solo'

There are, at least, 3 ways to debug this:

1) Plain old ruby debug

To debug this you can set a breakpoint at that offending line:

$ ruby -r debug your_program.rb

# Set a breakpoint where problem arises
break /var/lib/gems/2.0.0/gems/chef-11.6.2/lib/chef/knife/edit.rb:5

# Set a poor-man debug `puts` to find out where is a class defined
class Object
  def self.inherited(klass)
    targets = %w(Edit Chef::Knife::Edit)
    puts "#{klass.name} defined at #{__FILE__}:#{__LINE__}" if targets.include?(klass.name)
  end
end

# Now run until program ends or hits that breakpoint
cont

# Once it hits the breakpoing program will pause there and you can play around but the previus `puts` should already have showed where the `Edit` class is first defined.

#=> Chef::Knife::Edit defined at /some/pissing/file:432

2) With gem pry

You could also use pry.binding to stop the program at that line and look around to see what's happening by temporary editing edit.rb

$ vim /var/lib/gems/2.0.0/gems/chef-11.6.2/lib/chef/knife/edit.rb + 5

# Add this code before the offending line:
require 'pry'
binding.pry

Will also need to include gem "pry" in your Gemfile for that to work and run the program with bundle exec don't forget.

Program will stop there (at the line binding.pry) before continuing and then you can use pry goodness to find out where that class was already defined

[1] pry(main)> ? Bundler
#=> From: .../gems/bundler-1.3.5/lib/bundler.rb @ line 9

[2] pry(main)> ? Chef::Knife::Edit
#=> From: xxxxxxx.rb @ line xx

3) With gem pry-rescue

Also there is pry-rescue gem which will "start a pry session whenever something goes wrong"

$ gem install pry-rescue pry-stack_explorer
$ rescue your_program.rb

Or, if running your program through bundle exec add this to your Gemfile

group :development do
  gem 'pry-rescue'
  gem 'pry-stack_explorer'
end

And the program will enter a pry session whenever an exception is raised!

Sorry for giving so many options, hope one helps!

like image 68
Leo Gallucci Avatar answered Apr 26 '23 02:04

Leo Gallucci