Ruby mixin gives unidentified constant error - ruby

In irb, I do this
class Text
include FileUtils
end
I get: NameError: uninitialized constant Test::FileUtils
If I just do: include FileUtils (i.e. now class) everthing works.
What gives?

You need to make sure Ruby knows about the FileUtils module. That module isn't loaded by default:
>> FileUtils
NameError: uninitialized constant FileUtils
from (irb):1
>> require 'fileutils'
=> true
>> FileUtils
=> FileUtils
Don't worry too much about the error NameError: uninitialized constant Text::FileUtils - when you try to include a constant that Ruby doesn't know about, it looks in a few places. In your case, first it will look for Text::FileUtils and then it will look for ::FileUtils in the root namespace. If it can't find it anywhere (which in your case it couldn't) then the error message will tell you the first place it looked.

Did you try?
class Text
include ::FileUtils
end
This assumes that FileUtils is not within a module.

This is an old thread, but still if any bumps on this thread to find an answer. One just needs to add below line on top of his code (or anywhere outside the class/method/module)
require 'fileutils'
Including in the class does not works, may be it used to work in older versions.

Related

Ruby Uninitialized constant error when gem is run outside of bundle exec

I have a simple gem that creates an MD5 from a string.
module SimpleMD5
require 'digest/md5'
def self.md5_string(string)
Digest::MD5.hexdigest(string)
end
end
Running bundle exec bin/console and calling the method works fine
require 'simple_md5'
SimpleMD5.md5_string('test')
=> 098f6bcd4621d373cade4e832627b4f6
Once the gem is built using rake build and rake install using the IRB console and the same example above I get an error.
NameError: uninitialized constant SimpleMD5::Digest
Am I missing a step when the gem is built?
You're missing the module definition, so use this pattern:
require 'digest/md5'
module SimpleMD5
def md5_string(string)
Digest::MD5.hexdigest(string)
end
extend self
end
The SimpleMD5 name is not generated automatically, you must declare it somewhere.
Here extend self means you can mix-in the module with include SimpleMD5 as well as just use it straight-up as you do in your example.
Don't forget two things: In Ruby return is implicit, there's no need to use that unless you're exiting your function early, and MD5 is a pretty terrible hashing algorithm for 2016. Unless you're using it for backwards compatibility, use something better like SHA256 or SHA512.

undefined method `to_a' for "include Rubeus::Swing\n":String

I installed rubeus using the command below:
jruby -S gem install rubeus
bundle install
Then when i execute:
include Rubeus::Swing
I get this error :
undefined method `to_a' for "include Rubeus::Swing\n":String
So I think gem installed the wrong version, because method to_a is no longer supported in Ruby 1.9.x for strings
How can I fix this?
code:
require 'rubygems'
require 'java'
require 'rubeus'
include Rubeus::Swing #it's where everything crashes :-)
UPDATE
It seems the problem is with the jirb, I saved the code in a file and ran the code with jruby, and everything went well... I'm confused, what's wrong with jirb?
I'm not sure why, but I can confirm that Rubeus breaks jirb:
$ irb-jruby-1.7.3
irb(main):001:0> require 'rubeus'
=> true
irb(main):002:0> 1
NoMethodError: undefined method `to_a' for "1\n":String
Things do seem to work fine when non-interactively interpreting a script. One workaround is to simply add to_a back into String:
class String
def to_a
lines.to_a
end
end
# => nil
require 'rubeus'
# => true
include Rubeus::Swing
# => Object
The only issue I've noticed so far is that require 'rubeus' still breaks jirb in a second way: I now need to press Enter twice for every input.

LoadError: cannot load such file -- directory/file_name

I have a file structure like
root
|--lib
|--root.rb
|--extensions
|--strings.rb
I want to be able to use methods in string.rb in root.rb file.
So I added require 'extensions/strings' at the top of root.rb file.
But I get LoadError: cannot load such file -- extensions/strings.rb error.
How do I avoid this?
You can try the below:
require File.dirname(__FILE__) + "/extensions/strings"
Use require_relative if you are in Ruby 1.9 or later. In root.rb, write:
require_relative 'extensions/strings.rb'
I found the answer I am looking for here.
I used jandot's solution.
Dir[File.dirname(__FILE__) + '/extensions/*.rb'].each {|file| require file }
Edit after some testing,
For some reason, this doesn't throw any error message, but it doesn't seem to be loading the actual Ruby file.
I tried adding this to extensions/strings.rb
class Dog
def self.bark
puts "bark"
end
end
And ran it on irb.
1.9.3-p0 :001 > require 'rhapsody'
=> true
1.9.3-p0 :002 > Dog
NameError: uninitialized constant Dog
from (irb):2
from /Users/jasonkim/.rvm/rubies/ruby-1.9.3-p0/bin/irb:16:in `<main>'
So it's not finding the Dog class in extensions/strings.rb for some reason.
Edit after reading a guid in rubygems.org
When I start irb, I had to go irb -Ilib -rextensions
The guide explains the situation this way
We need to use a strange command line flag here: -Ilib. Usually RubyGems includes the lib directory for you, so end users don’t need to worry about configuring their load paths. However, if you’re running the code outside of RubyGems, you have to configure things yourself.
require_relative '../lib/extensions/strings'
Works for me.

Can I determine which paths RubyGems added to the load path to make my command line app work?

In a gemspec, I can specify the require_paths, which represent paths I want to be able to require from at runtime. These get put into the $LOAD_PATH by RubyGems.
My question is: is there a way I can determine what these paths are at runtime? Can I examine elements of $LOAD_PATH and know which ones were added just for my gem?
Update: Ultimately, I would like to dynamically load ruby files from inside the gem, e.g.
load_from 'foo/bar'
And have that find $MY_GEMS_LIB_DIR/foo/bar/*.rb. I can certainly go through the entire $LOAD_PATH looking for foo/bar, but I'd rather restrict it just to the gem.
I don't know if I understood your needing (my english is bad :-/ ); anyway, if the problem is to determine the directories that will be loaded when you require a gem you can use Gem::Specification.lib_dirs_glob:
Gem::Specification.find_by_name('irbtools').lib_dirs_glob
#=> "/home/my_user/.rvm/gems/ruby-1.9.3-p125/gems/irbtools-1.2.2/lib"
Gem::Specification.find_by_name('xyz').lib_dirs_glob
# raises a Gem::LoadError
So a possible implementation of load_from could be:
def load_from(gem_name, path)
path_to_load = File.join(Gem::Specification.find_by_name(gem_name).lib_dirs_glob, path)
Dir.glob(path_to_load).each(&method(:load))
end
Trying to load Thor::CoreExt :
Thor::CoreExt #=> NameError: uninitialized constant Thor
load_from 'thor', 'thor/core_ext/*.rb'
Thor::CoreExt #=> Thor::CoreExt
This works on my machine with ruby 1.9.3 and gem 1.8.21 .
If I understand you correctly, this should do (Ruby 1.9.3):
before = $LOAD_PATH.dup
require 'the_gem'
added_paths = $LOAD_PATH - before
Of course, this will include the paths added by the dependencies.
You can use the $: global in irb. There is also the gem which command which gives you a library path, but I'm not sure if that includes exactly what you want.
Looks like Gem.find_files may help you.

Ruby Module Help -- Looking in wrong directory?

Hey everyone! I am having trouble with understanding modules -- I have two files, one named "modfile.rb" with the module, and one named "main.rb" that runs the code:
# modfile.rb
module Module1
def method1
puts "SUCCESS!"
end
end
# main.rb
require 'modfile'
Module1.method1
Unfortunately, instead of SUCCESS! appearing on my screen, I get this:
<internal:lib/rubygems/custom_require>:29:in 'require': no such file to load -- modfile (LoadError)
from <internal:lib/rubygems/custom_require>:29:in 'require'
from main.rb:1:in '<main>'
I think (though I may be wrong) that Ruby is looking to the lib/.... file inside the Ruby directory on my computer, while modfile.rb is saved in the same directory as main.rb. How do I fix this problem (other than by moving the module's file?)
PS. one guide suggested I add the line "require 'rubygems'" but I already did and got the same error.
Check into the differences between require and require_relative in Ruby: require vs require_relative - best practice to workaround running in both Ruby <1.9.2 and >=1.9.2
In Ruby 1.9 the . directory was removed from the search path. To fix the problem this generated they added require_relative.
If modfile.rb and main.rb are in the same directory, make sure that you aare calling main.rb from the directory it's in, ie:
ruby main.rb
As I believe that is the directory that the Ruby interpreter will be looking in for any require files.
Edit: as #the-tin-man points out, the behaviour has changed for Ruby 1.9.
To be completely on the safe side, you can do:
require File.join(File.dirname(__FILE__), "modfile")
One other thing:
def method1
... should be:
def self.method1
... since you are calling the method as a class level method.

Resources