Weird LoadError on custom ruby gem - ruby

I have a custom gem and am encountering a really weird LoadError when I install it as a gem and attempt to require it in irb.
Everything works fine with my rspec tests inside the project folder. This only occurs when using it as an actual gem in irb.
The file it throws a LoadError exception at (/lib/mws/api/order_response.rb) does in fact exist. I've tried renaming the file and updating the file that requires it (/lib/mws.rb). I've tried recreating the file thinking maybe there was a permissions issue. Nothing works.
If I comment out the require line for that specific file, everything works. There's nothing special about the file. There's 4 other files nearly identical to it (*_response.rb).
I feel like I'm taking crazy pills. I must being overlooking something but I sure don't see it.
Trace:
chris#Samus:~$ irb
1.9.3p194 :001 > require 'mws'
LoadError: cannot load such file -- mws/api/order_response
from /Users/chris/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
from /Users/chris/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
from /Users/chris/.rvm/gems/ruby-1.9.3-p194/gems/mws-0.1.18/lib/mws.rb:14:in `<top (required)>'
from /Users/chris/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:60:in `require'
from /Users/chris/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:60:in `rescue in require'
from /Users/chris/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:35:in `require'
from (irb):1
from /Users/chris/.rvm/rubies/ruby-1.9.3-p194/bin/irb:16:in `<main>'
File with the requires (/lib/mws.rb)
require 'mws/base'
require 'mws/connection'
require 'mws/utility'
require 'mws/api/seller'
require 'mws/api/product'
require 'mws/api/order'
require 'mws/api/report'
require 'mws/api/general_response'
require 'mws/api/product_response'
require 'mws/api/report_response'
require 'mws/api/seller_response'
require 'mws/api/order_response' # <--- the offending line
module MWS
# #see Base#initialize MWS::Base for instantiation details.
# #return [Base] returns MWS::Base object.
def self.new(merchant_id, access_key, secret_key)
MWS::Base.new(merchant_id, access_key, secret_key)
end
end
# The below is for documentation generation purposes.
# MWS is a wrapper for the Amazon Marketplace Web Service (MWS) API.
module MWS
# API handles all the Amazon MWS API specific stuff.
module API
end
# Utilities contains various functions needed throughout MWS. Utilities is a mixin to multiple classes.
module Utilities
end
end
File I'm requiring (/lib/mws/api/order_response.rb):
module MWS
module API
# Class for parsing Amazon's XML responses into managable objects.
class OrderResponse
# Include GeneralResponse instance methods as class methods
extend GeneralResponse
end
end
end
And my file structure

For anyone interested, I was using Jeweler to handle building this gem. As it turns out, Jeweler uses your Git repository when building a gemspec.
If you haven't added all required files to your git repository, Jeweler's gemspec rake task will not include them when generating a new gemspec file.

Can should check in /Users/chris/.rvm/gems/ruby-1.9.3-p194/gems/mws-0.1.18/lib/mws/api if the file lies there (and doesn't have obscure permissions).
If that's not the case, you probably forgot to add it in your gemspec.
If it is there, please try requiring/loading it with the absolute path (for debugging purpose).

Related

Include module not working in gem

I have a gem called private_lib.
The file lib/private_lib.rb contains the following:
require 'private_lib/version'
require 'private_lib/handicap'
require 'private_lib/traversal_cap'
module PrivateLib
end
The lib/private_lib/handicap.rb file contains the following
# module for handicap functions
class Handicap
include TraversalCap
-- other code
end
and the file lib/private_lib/traversal_cap.rb contains the following
module TraversalCap
def some_method
end
-- other code
end
I also have a test file spec/handicap_spec.rb which contains the following
require "spec_helper"
describe Handicap do
include TraversalCap
-- some tests that access the ```Handicap``` class
-- some tests that access directly the traversal_cap some_method.
end
When I run rspec spec/handicap_spec, I get the following error
private_lib/lib/private_lib/handicap.rb:3:in `<class:Handicap>': uninitialized constant Handicap::TraversalCap (NameError)
from private_lib/lib/private_lib/handicap.rb:2:in `<top (required)>'
Why isn't the handicap class seeing the traversal_cap module?
It is because of the order you require the files.
At the time the line require 'private_lib/handicap' is run it reads the handicap.rb file and hits the line where you include TraversalCap. But you haven't yet run require 'private_lib/traversal_cap' at this point so the module is undefined.
Quick fix is to change the order of the require calls, or alternatively put require 'private_lib/traversal_cap' at the top of the handicap file.

How can I call Rake methods from a module

I have a lot of utility functions in my rake files, some of which create rake tasks. I want to move these utility functions into a module to avoid name clashes, but when I do the rake methods are no longer available.
require 'rake'
directory 'exampledir1'
module RakeUtilityFunctions
module_function
def createdirtask dirname
directory dirname
end
end
['test1', 'test2', 'test3'].each { |dirname|
RakeUtilityFunctions::createdirtask dirname
}
The error I get is:
$ rake
rake aborted!
undefined method `directory' for RakeUtilityFunctions:Module
C:/dev/rakefile.rb:8:in `createdirtask'
C:/dev/rakefile.rb:13:in `block in <top (required)>'
C:/dev/rakefile.rb:12:in `each'
C:/dev/rakefile.rb:12:in `<top (required)>'
As far as I can tell the directory method is placed on the ruby top-level by the following code in Rake:
# Extend the main object with the DSL commands. This allows top-level
# calls to task, etc. to work from a Rakefile without polluting the
# object inheritance tree.
self.extend Rake::DSL
Is there a simple way of call functions that have been placed on the top-level like this?
When you define a Module, the code within that module has a new scope.
So directory within RakeUtilityFunctions is in a different scope to the top-level code.
As you haven't defined directory within RakeUtilityFunctions you get an undefined method error.
Have a look at the Scope Gate section of this article.
I have figured it out now. With help from #ReggieB, I discovered this question: ways to define a global method in ruby.
It contained an excerpt from the rake change log.
If you need to call 'task :xzy' inside your class, include Rake::DSL into the class.
So, the easiest way to do this is to extend the module with Rake::DSL:
require 'rake'
directory 'exampledir1'
module RakeUtilityFunctions
self.extend Rake::DSL ### This line fixes the problem!
module_function
def createdirtask dirname
directory dirname
end
end
['test1', 'test2', 'test3'].each { |dirname|
RakeUtilityFunctions.createdirtask dirname
}

How to require file from `gem` which are not under `lib` directory?

I want to write spec for my rubocop custom cop. This gem has handy helpers defined here. I want to require it. How to achieve what?
I've tried to use Gem.find_files, and this gives me ability to require any file in that gem, but only under lib directory.
For example:
# this requires ...gems/rubocop-0.29.1/lib/rubocop/formatter/formatter_set.rb
require Gem.find_files('rubocop/formatter/formatter_set.rb').first
# but I need ...gems/rubocop-0.29.1/spec/support/cop_helper.rb
The following describes why I need it. I have spec/rubocop/my_custom_cop_spec.rb
require 'spec_helper'
require ? # What I should I write?
RSpec.describe RuboCop::Cop::Style::MyCustomCop do
it 'some test' do
inspect_source(cop, 'method(arg1, arg2)') # This helper I want to use from rubocop spec helpers
end
end
When I try plain require:
require 'rubocop/spec/support/cop_helper'
I receive error:
/home/user/.gem/ruby/2.0.0/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:274
:in `require': cannot load such file -- rubocop/spec/support/cop_helper
I found a solution that I think is a little more syntactically elegant:
gem_dir = Gem::Specification.find_by_name("my_gem").gem_dir
require "#{gem_dir}/spec"
I was so blinded, I already have path to file and able to get relative from it.
require 'pathname'
rubocop_path = Pathname.new(Gem.find_files('rubocop.rb').first).dirname
rubocop_path # => ...gems/rubocop-0.29.1/lib
require "#{rubocop_path}/../spec/support/cop_helper.rb"

Trying to create a proper ruby application (gem) for my Boulder codeschool class: lib classes not communicating correctly ('Uninitialized constant')

You can see everything in the file structure at github.com/ddd1600/simple_angel
I'm getting alot of errors while trying to create a ruby application (soon to be a gem) "the correct way", viz. by thoroughly dividing the logic into classes and "loader files" and all of that. Point is, I know how to do this code the simpler way, without obeying OO principles, but I want to do it "correctly".
So, first of all, the file structure is as follows---
root folder = ~/Develop/simple_angel
inside /simple_angel
- /lib
- Gemfile
- Rakefile
- simple_angel.gemspec
inside /lib
- simple_angel.rb
- /simple_angel
inside /lib/simple_angel
- company.rb
- search.rb
- version.rb
But, here are some basics.
Here is what I'm calling to run this program from the terminal (PATH when running is ~/Develop/simple_angel)
ruby -Ilib lib/simple_angel/search.rb
Here is search.rb
#these 'requires' are supposed to be loaded in lib/simple_angel.rb, so here I show
#them commented out
#
#require 'rubygems'
#require 'httparty'
#require 'json'
#require 'company'
module SimpleAngel
class Search
SEARCH_URL = "http://api.angel.co/1/startups"
def search(user_input)
response = HTTParty.get("#{SEARCH_URL}/#{user_input}")
parsed_response = JSON.parse(response.body)
Company.new(parsed_response)
end
end
s = SimpleAngel::Search.new
s = Search.new
x = s.search(6702)
p x
end
Here is the "loader" file, lib/simple_angel.rb (PS: what is a more formal title for this sort of file?)
require 'httparty'
require 'json'
require 'simple_angel/search'
require 'simple_angel/version'
require 'simple_angel/company'
module SimpleAngel
end
Lastly, when I (again), run "ruby -Ilib lib/simple_angel/search.rb" (with all of search.rb's 'requires' commented out (^&^), this is my error message:
[ddouglas#coders:~/Develop/simple_angel on master]
% ruby -Ilib lib/simple_angel/search.rb
lib/simple_angel/search.rb:15:in `search': uninitialized constant SimpleAngel::Search::HTTParty (NameError)
from lib/simple_angel/search.rb:24:in `<module:SimpleAngel>'
from lib/simple_angel/search.rb:8:in `<main>'
^&^ - now that we're all up to speed here, I might as well include the error that happened when I left search.rb's "requires" in place
% ruby -Ilib lib/simple_angel/search.rb ✹
/usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot load such file -- company (LoadError)
from /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
from lib/simple_angel/search.rb:6:in `<main>'
I can't say I understand the point the class is trying to make regarding splitting up your files.
The first error (uninitialized constant SimpleAngel::Search::HTTParty) is because from within SimpleAngel::Search, you call HTTParty. Try changing that to ::HTTParty to specify the root namespace.
The big picture issue, looking back on this issue, was that I probably just needed to activate my /lib folder within rails via this addition to config/application.rb
config.autoload_paths += Dir["#{config.root}/lib/**/"]
from there, code can be directly loaded via the file_name.rb => FileName class system from anywhere within rails

Metric Fu: RCov fails to load spec_helper

I am trying to run metric_fu on a Rails 3 application. All is good, with the exception of rcov. I have RSpec configured and my tests follow the spec/**/*.rb format and run fine in RSpec. Trying to check coverage with rcov, however, I get the following errors:
** Running the specs/tests in the [test] environment
No file to analyze was found. All the files loaded by rcov matched one of the
following expressions, and were thus ignored:
[/\A\/Users\/Eric\/\.rvm\/rubies\/ruby\-1\.8\.7\-p299\/lib/,
/\btc_[^.]*.rb/,
/_test\.rb\z/,
/\btest\//,
/\bvendor\//,
/\A\/Users\/Eric\/\.rvm\/gems\/ruby\-1\.8\.7\-p299#-backend\/gems\/rcov\-0\.9\.8\/lib\/rcov\/formatters\/base_formatter\.rb\z/,
/\bvendor\//,
/\bconfig\//,
/\benvironment\//,
/\/gems\//,
/\/Library\//,
/\/usr\//,
/spec/]
You can solve this by doing one or more of the following:
* rename the files not to be ignored so they don't match the above regexps
* use --include-file to give a list of patterns for files not to be ignored
* use --exclude-only to give the new list of regexps to match against
* structure your code as follows:
test/test_*.rb for the test cases
lib/**/*.rb for the target source code whose coverage you want
making sure that the test/test_*.rb files are loading from lib/, e.g. by
using the -Ilib command-line argument, adding
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
to test/test_*.rb, or running rcov via a Rakefile (read the RDoc
documentation or README.rake in the source distribution).
/Users/Eric/.rvm/rubies/ruby-1.8.7-p299/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require': no such file to load -- spec_helper (LoadError)
from /Users/Eric/.rvm/rubies/ruby-1.8.7-p299/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
from ./spec/models/account_spec.rb:1
from /Users/Eric/.rvm/gems/ruby-1.8.7-p299#backend/gems/rcov-0.9.8/bin/rcov:511:in `load'
from /Users/Eric/.rvm/gems/ruby-1.8.7-p299#backend/gems/rcov-0.9.8/bin/rcov:511
from /Users/Eric/.rvm/gems/ruby-1.8.7-p299#backend/bin/rcov:19:in `load'
from /Users/Eric/.rvm/gems/ruby-1.8.7-p299#backend/bin/rcov:19
When I run rcov directly, it appears that part of the issue is rcov not correctly loading the spec_helper in my specs, which is required as "require 'spec_helper'".
Any help on how to resolve this? Thanks.
Adding "-Ispec" to the Metric-Fu configuration fixes this.

Resources