Cannot load a custom gem - ruby

I have a real newbie problem. I wrote a very small (one-file) library and I wanted to publish it in a gem so that I can use it in other projects modularly. I used the following gemspec:
Gem::Specification.new do |s|
s.name = 'symbolize-array'
s.version = '1.0.0'
s.date = '2013-11-22'
s.summary = "Symbolizes strings in arrays"
s.description = ""
s.files = ["lib/array.rb"]
s.homepage =
'https://github.com/renra/symbolize-array-ruby'
s.license = 'MIT'
end
I build the gem. Fine. I publish the gem. Fine. I install the gem from rubygems. Fine. But when I run irb and do require 'symbolize-array' I get:
LoadError: cannot load such file -- symbolize-array
from /home/renra/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in `require'
from /home/renra/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in `require'
from (irb):4
from /home/renra/.rvm/rubies/ruby-2.0.0-p247/bin/irb:13:in `<main>'
As you can see from the backtrace I use rvm. When I run 'gem environment' and I go to the gem path I can see my gem is installed just like the others. I can require the others, but I cannot require my gem. So I guess this is not a problem with the load path (I've seen questions that were answered like that) but maybe in the way I built the gem. Grateful for your ideas.

You would need to require "array" to load your library, which may not work at all due to name clashes with other gems. When you install a gem, it just adds its library folder to the search path, and requires find files by name (without the .rb), they don't reference gem names.
Take a look at the naming conventions for gem components and also the link http://guides.rubygems.org/name-your-gem/
I suspect you should name the file "lib/symbolize_array.rb" and probably the gem name should be "symbolize_array" - ideally it would also implement a class or module SymbolizeArray in that case, but that is less important.

Related

Why is the executable not loading my cli file

I am following the gem guide in the bundler documentation.
when i reached the command line part where i have to require 'foodie/cli' on the executable, i keep getting error.
/Users/suyesh/.rbenv/versions/2.3.3/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- foodie/cli (LoadError)
from /Users/suyesh/.rbenv/versions/2.3.3/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from exe/foodie:2:in `<main>'
here is my code in the executable
#!/usr/bin/env ruby
require 'foodie/cli'
Foodie::CLI.start
here is my cli which is in lib/foodie/cli.rb
require 'thor'
require 'foodie'
module Foodie
class CLI < Thor
desc "portray ITEM", "Determines if a piece of food is gross or sdeliciour."
def portray(name)
puts Foodie::Food.portray(name)
end
end
end
What am i doing wrong?
Depending on how you call your executable and how your paths are set up it should work (tm).
Use bundle exec path/to/my/executable in your development environment (assuming you are writing a gem - which is nearly always a good idea). If you followed the other steps in the Bundler tutorial I believe you should have a gemspec file which tells bundler where to look for ([lib/]foodie/cli.rb).
Use ruby -Iinc/lude/dir/for/example/lib path/to/my/executable to tell your ruby to (temporarily) also look in the directory inc/lude/dir/for/example/lib for source files (in your case foodie/cli.rb). Since you are learning bundler, dont use this approach, but it might be interesting to others, and to cast some light in the area where lib-, load- and include-paths live.

Why can't I require a gem from within the .gemspec?

I can't require third party code in my .gemspec file. I would like to require a semver library to manage my version number. Why can't I require gems inside my .gemspec?
I have a workaround for my particular problem. What I am interested in the specific reason I can't require code from inside a gemspec. I feel like I am missing something about how Rubygems work. Thanks!
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'semver'
Gem::Specification.new do |spec|
spec.add_dependency "semver2", "~> 3.4.2"
spec.version = SemVer.find.to_s[1..-1]
end
Running bundle install results in the following error:
$ bundle
[!] There was an error parsing `Gemfile`: There was a LoadError while loading example.gemspec:
cannot load such file -- semver from
/opt/pose/auto/stack-overflow/example/example.gemspec:3:in `<main>'
Obviously there is some point before which you cannot depend on 3rd party gems to be on your LOAD_PATH. I am asking for an explanation of where that point is. My guess is because my Gemfile references my gemspec and Bundler had not loaded all the dependencies yet, but that is a guess.
A .gemspec is just a Ruby script like any other Ruby script. Basically the only thing that is "special" is that it is run in an environment where certain libraries have already been required, such as rubygems/specification.
requireing libraries works just like in any other Ruby script.

ruby gem require_relative cannot load such file

I've looked around online and on SO and most of the answers to this question say that I should be using require_relative but I am using it so I don't know what the problem might be. I'm trying to build a ruby gem and my folder structure looks like this
--xmlmc-rb/
--lib/
--xmlmc-rb/
api.rb
interface.rb
version.rb
xmlmc-rb.rb
Within xmlmc-rb.rb I am requiring all three of the files under the xmlmc-rb/ directory like this
require_relative "xmlmc-rb/version"
require_relative "xmlmc-rb/interface"
require_relative "xmlmc-rb/api"
require 'net/http'
require 'nokogiri'
require 'base64'
But I keep getting an error
/Library/Ruby/Gems/2.0.0/gems/xmlmc-rb-0.1.1/lib/xmlmc-rb.rb:2:in `require_relative': cannot load such file -- /Library/Ruby/Gems/2.0.0/gems/xmlmc-rb-0.1.1/lib/xmlmc-rb/interface (LoadError)
from /Library/Ruby/Gems/2.0.0/gems/xmlmc-rb-0.1.1/lib/xmlmc-rb.rb:2:in `<top (required)>'
from /Library/Ruby/Site/2.0.0/rubygems/core_ext/kernel_require.rb:128:in `require'
from /Library/Ruby/Site/2.0.0/rubygems/core_ext/kernel_require.rb:128:in `rescue in require'
from /Library/Ruby/Site/2.0.0/rubygems/core_ext/kernel_require.rb:39:in `require'
from xmlmc_test.rb:1:in `<main>'
When I manually copy all the files into the main rb file everything works. Initially I thought it was a naming error since the casing of the files under xmlmc-rb/ weren't uniform, but I fixed that, made them all lowercase names and the same error persists.
As I didn't understand very well your gem name, I will show you how I did:
require "password_control/scrypt/ScryptHash"
In my case I have another directory inside the password_control folder. But if my file was in the password_control directory, the require would be:
require "password_control/ScryptHash"
I got this working by copying everything out of interface.rb deleting the file and recreating it. Strange why that happened.
I had the same error building a Ruby Gem.
I built and installed the gem:
gem build <gemname>.gemspec
gem install <gemname>-0.0.1.gem
I checked where the gem was installed:
gem env home
gem list -d
I tried to load the gem in Interactive Ruby (IRB):
irb
require '<gemname>'
It resulted in error:
LoadError: cannot load such file -- /Users/<username>/.rbenv/versions/2.4.2/lib/ruby/gems/2.4.0/gems/<gemname>-0.0.1/lib/my_gem_subdirectory/module_name
I was using require_relative './my_gem_subdirectory/module_name' in Ruby files in the lib directory to import modules and classes from the sub-directories.
I solved the error by updating the Gemspec .gemspec to include all files and subdirectories. Initially I only had s.files = ['lib/<gemname>.rb']. But I read the documentation http://guides.rubygems.org/specification-reference/#files and changed it to:
Gem::Specification.new do |s|
...
s.files = ['lib/discrete_math.rb']
s.files += Dir['lib/*.rb']
s.files += Dir['lib/my_gem_subdirectory/**/*']
...
end

Can't use created gem on computer

I created a gem with the following gemspec file.
$:.push File.expand_path("../lib", __FILE__)
Gem::Specification.new do |s|
s.name = 'SomeToken'
s.version = '0.0.0'
s.date = '2013-08-04'
s.summary = "A gem for use with SomeToken."
s.description = "A gem for use with SomeToken."
s.authors = ["Jason Tanner"]
s.email = 'jasontanner328#gmail.com'
s.files = Dir.glob '**/*'
s.homepage = ''
s.license = ''
end
Then in my terminal I run
gem build sometoken.gemspec
Then,
gem install ./SomeToken-0.0.0.gem
The gem is successfully installed, so when I run irb and I run...
require 'SomeToken'
Which responds with the error
LoadError: cannot load such file -- SomeToken
from /Users/jason/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:51:in `require'
from /Users/jason/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:51:in `require'
from (irb):1
from /Users/jason/.rvm/rubies/ruby-2.0.0-p195/bin/irb:16:in `<main>'
I've tried changing the casing for the string, in numerous combinations but still get the same error. What's wrong with my gem and how can I fix it?
Try require 'some_token'.
Using require in general
require takes the name of a ruby file, not the name of a gem. For example, if you have the following directory structure
- foo.rb
- main.rb
Then in main.rb, you can use require 'foo' to use stuff from foo.rb.
Using require with gems
Notice that the first line of your gemspec has $:.push File.expand_path("../lib", __FILE__). This adds the lib directory of your gem to the search path. Thus, if you have
lib/
some_token.rb
then you should use require 'some_token'.
I don't know if Ruby 2.0.0 have this 'bug', but some Ruby versions must have a
require 'rubygems'
before you require any gem.
Guess it's worth a try :)

Created a simple gem, but irb can't see it

I created a simple gem by doing:
testgem.gemspec
Gem::Specification.new do |s|
s.name = 'testgem'
s.version = '0.0.1'
s.summary = "code generation"
s.authors = ['asdf']
end
created the following file layout:
testgem.gemspec
Gemfile
lib/
lib/testgem.rb
lib/testgem/other.rb
ran the following:
gem build testgem.gemspec
WARNING: no description specified
WARNING: no email specified
WARNING: no homepage specified
Successfully built RubyGem
Name: testgem
Version: 0.0.1
File: testgem-0.0.1.gem
installed it:
gem install ./testgem-0.0.1.gem
Successfully installed testgem-0.0.1
1 gem installed
tested to see if irb can see it:
irb
require 'testgem'
oadError: cannot load such file -- testgem
I'm using Ruby 1.9.3-p194
It seems to be installed if I do:
gem list
..
testgem (0.0.1)
..
What could be the issue?
You need to add your lib to the search path. Just add
$:.push File.expand_path("../lib", __FILE__)
on top of your .gemspec
When you use require in Ruby, you are trying to load a file, not a gem. The file could of course be contained in a gem, and by convention a gem will have a file with the same name as the gem itself so that if you wanted to use the gem foo you would use require 'foo'. This isn’t always the case though, for example to use the bcrypt-ruby gem you need to require 'bcrypt'.
Additionally a gem doesn’t necessarily have to contain any filles at all. An example of this is the rails gem, which doesn’t contain any files itself (at least in version 3.2), but has dependencies to the various Rails components, so that you can install them all in one step.
In your case, although you have a lib/testgem.rb file in your gems project directory, you are not including it in your gem. You need to specify which files should be included, the default is to not include anything.
To simply include all the files in your project directory, you can add something like:
s.files = Dir.glob '**/*'
to your gemspec.
You need to require 'rubygems' first.

Resources