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?
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'
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
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
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With