How to track what removed a module? - ruby

I have an issue that HTTP::auth is available under normal circumstances but not defined under a project with lots of dependencies.
I have the gem in Gemfile.lock, I have the necessary require 'http' statement. Issue is that already httpclient and http-cookie gems also modify same HTTP module.
The thing is that inside the project I only see what was defined by the http-cookie jar. But http is already required.
[3] pry(#<ReportPortal::HttpClient>)> ls HTTP
constants: Accept Cookie CookieJar
[4] pry(#<ReportPortal::HttpClient>)> require 'http'
=> false
My conclusion is that something uses remove_const to remove the HTTP module in the middle for whatever reason. And I want to find and violently destroy it.
Please give me ideas how to track this down.

Related

undefined local variable or method for extended module

NOTE: the question was edited to reflect the issue.
i would like to work with knife-api rubygem. enclosed a snippet of my code
require 'chef'
require 'chef/knife'
require 'knife/api'
module X
module Y
module Z
include Chef::Knife::API
def self.foo
resp = knife_capture :search, ['*:*']
puts resp
end
end
end
end
when X::Y::Z.foo is called, it returns
gems/knife-api-0.1.7/lib/knife/api.rb:41:in `ensure in knife_capture': undefined local variable or method `revert_io_channels' for X::Y::Z (NameError)
it appears that he enclosing scope functions (Chef::Knife within knife-api) are inaccessible within X::Y::Z.foo.
how should i make this work?
In a complete non-answer, do not use the knife-api gem. It should not exist. The correct gem to use if you want to access Chef API data from Ruby code is chef-api (I know, we're real creative with names). If you want to do something very small, check out the knife exec command which just exposes the raw Chef object API (not as refined as chef-api, but built in).
This gem is a fork of another project that is no longer maintained. Looking at the gem code, it appears there were several issues introduced to the latest version (0.1.7) through some bad refactoring of the original code. That version was released a year ago and it hasn't had any commits since. The repo also does not accept issue tickets, and it has no tests. If you must use this gem, I would try a pessimistic constraint gem 'knife-api', '< 0.1.7' and see if that works. However it might be a better idea to skip it entirely. I made an attempt to fix the issues and submit a PR. You can also try pulling the gem from my forked repo https://github.com/msimonborg/knife-api

Should I depend on gems I'm extending?

Suppose there's gem that implements authentication strategy for Warden or a storage engine for Paperclip or an ActiveRecord database adapter. Should it include the gems it supposed to be used with as regular dependencies? If so, what should be the version constraints? It certainly has to include "parent" gems as development dependencies but what about regular ones?
It’s all up to you. Unless you rely in your code on gem presence (read: surround all your code with if const_defined?('Paperclip') or like,) your gem might gracefully reject to operate unless the necessary dependencies are already included in the target project. The version should correspond the version you have your code tested against.
As a good example of the case when direct dependence is not a good choice, would be the “umbrella” gem, simplifying work with different, say, authorization engines. One won’t require all these devises, pundits, and family. Instead one should do “clever” initialization:
case
when Kernel.const_defined?('Devise')
Logger.debug 'Will initialize Devise bridge.'
# initialization of bindings etc.
when Kernel.const_defined?('Pundit')
Logger.debug 'Will use Pundit bridge.'
# initialization of bindings etc.
...
else
Logger.warn 'No authorization backend found.'
raise
end
Or, imagine the logger, that might send airbrakes. For the logger to operate, the airbrake presense is not crucial. Hence one might check the presence of airbrake gem in the target project and switch the additional functionality on on success.
Hope it helps.

How do i implement factual in Ruby?

I chose "factual-api" gem after looking at the factual website. May I know how do I set it up and use the function to get the locations of those areas? Can I write it in the controller/model?
After trying to install the gem, I get this when I look at my gemfile:
Gem "factual-api" is unavailable in SDK 'RVM: ruby-1.9.2-p290
This inspection warns about unavailable gems inside the current SDK. The IDE needs the gems to provide come completion, navigation and analysis. An appropriate quick-fix is available to install the required gems.
When I run the command bundle install, I do not have any errors. But when I called:
factual = Factual.new("YOUR_KEY", "YOUR_SECRET")
I get this:
NameError: uninitialized constant Factual
What am I doing wrong now? What should be the right way to do so?
This answer is a bit late, but I'm posting it anyway so it can be marked as answered.
As mentioned in the comments the recommended approach is to use Factual's Ruby Driver which can be found at http://github.com/Factual/factual-ruby-driver or installed with the following in your Gemfile:
gem 'factual-api', :require => 'factual'
If not using a Gemfile remember to manually require 'factual' somewhere. I also like to put an initializer in the config folder with the OAuth details if it's a private repository that looks something like this:
class Factual
KEY = 'YOUR-OAUTH-KEY'
SECRET = 'YOUR-OAUTH-SECRET'
end
This allows you to access the Factual API anywhere in your app with
factual = Factual.new Factual::KEY, Factual::SECRET

What is the origin of System::Process.new?

Where is the origin of Process.new and where is it doccumented? I have looked in the Ruby docs at the process module and I cannot figure out how this is declared.
The code I am trying to replicate is in the Ruby God gem in lib/god/conditions/memory_usage.rb:66:
process = System::Process.new(self.pid)
#timeline.push(process.memory)
System::Process isn't part of Ruby, it comes from God (the gem) itself. You can view its source if you want.
It's referable as System::Process in the file you reference because you're already in the God module, so Ruby resolves it within that namespace.

How to work with classes and dependences in ruby

I have changed this question to better reflect what it is I do not understand.
For example if I try to access the methods in the railties class AppBuilder.
require 'rails/generators/rails/app/app_generator'
g = Rails::AppBuilder.new
puts g.rakefile.inspect
I get an error message activesupport-3.1.3/lib/active_support/secure_random.rb:5:in `': uninitialized constant SecureRandom (NameError)
I do not understand this. Should not each class be "independent" from other classes? Is that not the whole point of object oriented programing?
And now If it is not so more importantly how can I figure out what dependences I need to add? Is it some kind of workflow to solve this? Can I somehow figure out what dependencies to add looking at the documentation? Do this problem have something to do with load path? Can I load all dependences from a gem or rails or whatever? I just don't get it!
doc: http://api.rubyonrails.org/classes/Rails/AppBuilder.html github: https://gist.github.com/rails/rails/blob/master/railties/lib/rails/generators/rails/app/app_generator.rb
there is no easy way to find out which dependencies are used within AppBuilder, cause most of the dependencies are setup somewhere else. so most of the times you need to do some trial and error to get the dependencies right.
the code that you posted has bad style. please get familiar with how to write ruby code properly. buy yourself a book i.e. eloquent ruby or just start reading ruby blogs.
dependencies in ruby is quite simple. every file that you require will be loaded and the load will recurse through the files and then load other requires. the loading will only work if all the required files are on the load path. this load path is similar to your system path and you can add directories to it to tell ruby where to look for files.
in general, there are dedicated entry-points for libraries and their dependencies. those are normally documented, so that if you use them, you get all dependencies right from the beginning. an example for this would be to require 'rails' in order to use rails or require 'active_support/all' if you just want to use active-support. if you wan't to chery-pick files/classes than you are on your own finding out which other classes you need. that part has nothing to do with oop, it's more an dependency-issue (other languages have explicit decleration of dependencies).
in your case, the next step would be to add require "securerandom" to the beginning of your file and then check wich error comes up next.

Resources