Call one Ruby Script from Another - ruby

I am having a perplexing problem. I want to call one ruby script from another.
With this in mind, I create a testscript.rb and executed it, it contains this code,
require './paypal.rb'
puts paypal['L_AMT0']
This code returns a number, which is my paypal balance. It relies on a paypal.rb file which uses the ruby-paypal gem. When I do ruby testscript.rb I get the output of my paypal balance, which means it is working properly. This tells me that my method for calling one RB from another is okay, since, in the above scenario, testscript.rb is getting a variable that is returned from paypal.rb.
Using this same logic, I inserted the above code into another program which is called SiriProxy. It is a ruby program. I need it to get my paypal balance.
So Inside that program, I did a require paypal.rb, it failed because it could not find it, so I set an absolute path in require which fixed it.
However, when SiriProxy (the other ruby rb giving me an issue) trys to run puts paypal['L_AMT0'] it results in an error and ends the program.
This is the error,
[Info - Plugin Manager] Say: Checking Paypal Balance
/home/siriproxy/.rvm/gems/ruby-1.9.3-p194#SiriProxy/gems/siriproxy-0.3.0/plugins/siriproxy-example/lib/siriproxy-example.rb:47:in `block in <class:Example>': undefined local variable or method `paypal' for #<SiriProxy::Plugin::Example:0x931a228> (NameError)
from /home/siriproxy/.rvm/gems/ruby-1.9.3-p194#SiriProxy/bundler/gems/cora-1edcfb9073d5/lib/cora/plugin.rb:47:in `instance_exec'
from /home/siriproxy/.rvm/gems/ruby-1.9.3-p194#SiriProxy/bundler/gems/cora-1edcfb9073d5/lib/cora/plugin.rb:47:in `block (2 levels) in process'
In the above output it appears the issue is it does not understand "paypal", as seen here:
undefined local variable or method `paypal'
However, I do not understand why, since in testscript.rb I do the exact same thing and it works.
Can anyone help? Thank you.

Seems like #CodeGnome is right.
From the Kernel documentation:
require(name) → true or false
Loads the given name, returning true if successful and false if the
feature is already loaded.
require_relative(string) → true or false
Ruby tries to load the library named string relative to the requiring
file’s path. If the file’s path cannot be determined a LoadError is
raised. If a file is loaded true is returned and false otherwise.

Loading Files from the Current Directory
I don't know anything about your library or its internals, but it looks like your require statement may be wrong. If you want to load a file from the current directory in Ruby 1.9.3, you should use:
require_relative 'paypal'
Bundler and Gems
If it's a gem that you've installed as part of a bundle (e.g. the gem is defined in a Gemfile), then providing a path in your require statement is wrong. Instead, you need to require the bundled gem as follows:
require 'bundler/setup'
require 'paypal'

Related

Cannot open file ruby.png in Gosu using Learn Game Programming with Ruby

I'm using the Learn Game Programming with Ruby book and I'm trying to just execute the sample code.
I get the following error, using the sample code.
❯ ruby WhackARuby/WhackARuby_1/whack_a_ruby.rb code
/Users/noahclark/.rvm/gems/ruby-2.2.1/gems/gosu-0.10.4/lib/gosu/patches.rb:40:in `initialize': Cannot open file ruby.png (RuntimeError)
from /Users/noahclark/.rvm/gems/ruby-2.2.1/gems/gosuu0.10.4/lib/gosu/patches.rb:40:in `initialize'
from WhackARuby/WhackARuby_1/whack_a_ruby.rb:15:in `new'
from WhackARuby/WhackARuby_1/whack_a_ruby.rb:15:in `initialize'
from WhackARuby/WhackARuby_1/whack_a_ruby.rb:70:in `new'
from WhackARuby/WhackARuby_1/whack_a_ruby.rb:70:in `<main>'
The sample code looks like this:
require 'gosu'
class WhackARuby < Gosu::Window
def initialize
super(800, 600)
self.caption = 'Whack the Ruby!'
#image = Gosu::Image.new('ruby.png')
end
end
Any thoughts on what could be going on here? I've tried changing the offending line to #image = Gosu::Image.new('./ruby.png') for example and that didn't help.
I doubt this is the cause, but my ruby version is ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-darwin14]
EDIT includes file path:
Invariably the problem is because the file doesn't exist where you think it is.
There are many ways to reference a file. The File documentation has expand_path, realpath, absolute_path, all of which make it easy to reference a file based on an absolute or relative path, and relative to the currently running file, application or a particular directory. How to use them is covered in their examples.
It's important to make sure you know what directory the code considers it's current-working-directory, and/or where the file is. The first is important when using a relative path, and the second is if you don't want to care about your current path and know that the file ALWAYS exists in a certain place.
And, then there's also the case when the file's name is different than what you think it is, or it doesn't even exist.
In my case the solution was using a more explicit filepath:
Gosu::Image.new("#{__dir__}/ruby.png")

rake error: "warning: already initialized constant FileUtils::OPT_TABLE"

I've seen similar questions regarding this error, but all of them rails-related. I'm not using rails; I'm working on a local rake task that reads from a yaml file and then does stuff with the data. I'd rather not install bundler for this (the solutions for the similar rails issues suggest prepending with bundle exec), since this script is simple and thus shouldn't need it.
Here's the simplified code, (which gets the same error as the code I'm working on):
require 'FileUtils'
require 'yaml'
SOME_FILE = "#{Dir.pwd}/some_file.yaml"
task default: :foo
task :foo do
bar = File.open(SOME_FILE) { |yf| YAML::load( yf ) }
bar.each {|k,v| puts k}
end
And here's the list of errors:
/Users/jpalmieri/.rbenv/versions/2.0.0-p353/lib/ruby/2.0.0/FileUtils.rb:93: warning: already initialized constant FileUtils::OPT_TABLE
/Users/jpalmieri/.rbenv/versions/2.0.0-p353/lib/ruby/2.0.0/fileutils.rb:93: warning: previous definition of OPT_TABLE was here
/Users/jpalmieri/.rbenv/versions/2.0.0-p353/lib/ruby/2.0.0/FileUtils.rb:1272: warning: already initialized constant FileUtils::Entry_::S_IF_DOOR
/Users/jpalmieri/.rbenv/versions/2.0.0-p353/lib/ruby/2.0.0/fileutils.rb:1272: warning: previous definition of S_IF_DOOR was here
/Users/jpalmieri/.rbenv/versions/2.0.0-p353/lib/ruby/2.0.0/FileUtils.rb:1535: warning: already initialized constant FileUtils::Entry_::DIRECTORY_TERM
/Users/jpalmieri/.rbenv/versions/2.0.0-p353/lib/ruby/2.0.0/fileutils.rb:1535: warning: previous definition of DIRECTORY_TERM was here
/Users/jpalmieri/.rbenv/versions/2.0.0-p353/lib/ruby/2.0.0/FileUtils.rb:1537: warning: already initialized constant FileUtils::Entry_::SYSCASE
/Users/jpalmieri/.rbenv/versions/2.0.0-p353/lib/ruby/2.0.0/fileutils.rb:1537: warning: previous definition of SYSCASE was here
/Users/jpalmieri/.rbenv/versions/2.0.0-p353/lib/ruby/2.0.0/FileUtils.rb:1656: warning: already initialized constant FileUtils::LOW_METHODS
/Users/jpalmieri/.rbenv/versions/2.0.0-p353/lib/ruby/2.0.0/fileutils.rb:1656: warning: previous definition of LOW_METHODS was here
/Users/jpalmieri/.rbenv/versions/2.0.0-p353/lib/ruby/2.0.0/FileUtils.rb:1662: warning: already initialized constant FileUtils::METHODS
/Users/jpalmieri/.rbenv/versions/2.0.0-p353/lib/ruby/2.0.0/fileutils.rb:1662: warning: previous definition of METHODS was here
The script will run fine despite the warnings; the above code would puts the keys as expected, right after the warnings.
This warning shows up when I write require 'FileUtils'. If I write require 'fileutils' (all lower case) warning disappears.
This link may be helpful explaining the behavior. I think in essence ruby thinks FileUtils and fileutils are different modules, therefore imports it twice. Then the redeclaration of constants give warning messages.
Wanted to answer this clearly (two years after it was asked) in case anyone wanders in here.
First, note that require in Ruby does not load a Module, as in the object FileUtils that is in memory. It loads the file "fileutils.rb" from your hard drive. The ".rb" is omitted by convention but you could write require 'fileutils.rb'.
The purpose of require in Ruby is to load a file only once, as opposed to load which will reload the file every time it is used. The way require avoids loading a file multiple times is by recording the filename argument and skipping it if it if that filename is passed again.
When you first require a file, Ruby responds with true to indicate that it was loaded. If you require the same file again it will return false to indicate that it was already loaded:
> require 'fileutils'
=> true
> require 'fileutils'
=> false
Since the filename stored by require is case-sensitive, but the actual file lookup is not, fileutils.rb will still be found if you use caps in the name:
> require 'FileUtils'
=> true
But if something in your Ruby program already loaded that file without caps (in your case "yaml.rb" probably requires "fileutils" as well) you will reload the file and may see warnings:
> require 'fileutils'
=> true
> require 'FileUtils'
/bin/ruby/lib/ruby/2.3.0/FileUtils.rb:96: warning: already initialized constant FileUtils::OPT_TABLE
etc.
By convention Ruby files should be named in lowercase with underscores, e.g. "my_class.rb", so you would always use require 'my_class'.
Things get a little trickier if you are requiring using absolute or relative paths, e.g. require 'special_classes/my_class'. I suggest reading about require_relative and the Ruby load path ($LOAD_PATH).
I solved this similar issue when I list my gem items which named "fileutils" has two versions
fileutils (1.1.0, default: 1.0.2)
then I run
sudo gem uninstall fileutils -v 1.1.0
and solved
I found that these warnings don't appear and the script runs perfectly if I simply comment out or remove line 1 of my original code (require 'FileUtils'). Although I haven't browsed the code for Rake, it must already include FileUtils (which makes sense).
For the sake of completeness, here is my revised code (note that I removed the require 'FileUtils' line:
require 'yaml'
SOME_FILE = "#{Dir.pwd}/some_file.yaml"
task default: :foo
task :foo do
bar = File.open(SOME_FILE) { |yf| YAML::load( yf ) }
bar.each {|k,v| puts k}
end
I was having the same issue with Travis and the problem was that I forgot to use bundle exec rake db:setup instead of rake db:setup. Hope it helps someone :)

Using File::read in a provider's default.rb in Chef

I am trying to create an LWRP that will call the resource that is defined within itself. My cookbook's structure is as follows:
In the machine cookbook's provider, I have a code snippet as follows:
require 'chef/provisioning' # driver for creating machines
require '::File'
def get_environment_json
##environment_template = JSON.parse(File::read(new_resource.template_path + "environment.json"))
return ##environment_template
end
The code is only trying to read a json file and I am using File::read for it.
I keep getting an error as follows:
LoadError
cannot load such file -- ::File
Does anyone know how I can use File::read inside my LWRP's provider?
OK, so the prior two answers are both half right. You have two problems.
First, you can't require ::File as it's already part of Ruby. This is the cause of your error.
Second, if you call File.read you will grab Chef's File not ruby's. You need to do a ::File.read to use Ruby's File class.
require '::File'
Is incorrect and is causing the LoadError. Delete this line. You don't need it. File is part of the Ruby core and doesn't need to be required.
To further explain, the string argument to require represents the file name of the library you want to load. So, it should look like require "file", or require "rack/utils".
It happens becuase Chef already has a file resource. We have to use the Ruby File class in a recipe.We use ::File to use the Ruby File class to fix this issue. For example:
execute 'apt-get-update' do
command 'apt-get update'
ignore_failure true
only_if { apt_installed? }
not_if { ::File.exist?('/var/lib/apt/periodic/update-success-stamp') }
end
Source: https://docs.chef.io/ruby.html#ruby-class

Issues loading java class into gem in JRuby

I am trying to add JRuby support to my C-extension gem, by writing a Java class and executing it when the gem is installed on JRuby. The code in question lives on this branch, with the important files being the java class and the code to load it when used in JRuby
At this point, I am just trying to ensure I have my gem configured correctly, and fully expect it to fail the specs.
When I try to run rspec (or the gem in IRB for that matter) I get the following backtrace
NameError: cannot load Java class com.dockyard.PgArrayParser
get_proxy_or_package_under_package at org/jruby/javasupport/JavaUtilities.java:54
method_missing at /Users/dan/.rbenv/versions/jruby-1.6.7.2/lib/ruby/site_ruby/shared/builtin/javasupport/java.rb:51
PgArrayParser at /Users/dan/Projects/dockyard/pg_array_parser/lib/pg_array_parser.rb:6
(root) at /Users/dan/Projects/dockyard/pg_array_parser/lib/pg_array_parser.rb:3
require at org/jruby/RubyKernel.java:1033
require at /Users/dan/.rbenv/versions/jruby-1.6.7.2/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:36
(root) at /Users/dan/Projects/dockyard/pg_array_parser/lib/pg_array_parser.rb:2
require at org/jruby/RubyKernel.java:1033
require at /Users/dan/.rbenv/versions/jruby-1.6.7.2/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:36
(root) at /Users/dan/Projects/dockyard/pg_array_parser/lib/pg_array_parser.rb:1
require at org/jruby/RubyKernel.java:1033
require at /Users/dan/.rbenv/versions/jruby-1.6.7.2/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:36
(root) at /Users/dan/Projects/dockyard/pg_array_parser/spec/spec_helper.rb:1
load at org/jruby/RubyKernel.java:1058
load_spec_files at /Users/dan/Projects/dockyard/pg_array_parser/spec/parser_spec.rb:746
collect at org/jruby/RubyArray.java:2331
load_spec_files at /Users/dan/.rbenv/versions/jruby-1.6.7.2/lib/ruby/gems/1.8/gems/rspec-core-2.10.1/lib/rspec/core/configuration.rb:746
run at /Users/dan/.rbenv/versions/jruby-1.6.7.2/lib/ruby/gems/1.8/gems/rspec-core-2.10.1/lib/rspec/core/command_line.rb:22
run at /Users/dan/.rbenv/versions/jruby-1.6.7.2/lib/ruby/gems/1.8/gems/rspec-core-2.10.1/lib/rspec/core/runner.rb:69
autorun at /Users/dan/.rbenv/versions/jruby-1.6.7.2/lib/ruby/gems/1.8/gems/rspec-core-2.10.1/lib/rspec/core/runner.rb:10
call at org/jruby/RubyProc.java:270
call at org/jruby/RubyProc.java:224
Having recently worked on a JRuby extension myself, here are some of the gotchas which I have found through experiment -- and which seem to cause you problems too:
The java package must match the Ruby module in which your class sits. If your class is in the PgArrayParser module, your class must be in the pgarrayparser (all lowercase).
If you want to instantiate a PgArrayParserEngine class, then you BasicLibraryService must be called PgArrayParserEngineService.
When using #JRubyMethod, specify the name of the method.
I have found Yoko's article on the subject most useful, along with this recent post.
I have applied these different elements to your project here, and I can call the method from IRB -- and the first spec passes!

Ruby separate large source files into multiple files

I am writing a Ruby script which was supposed to be a small thing but has grown quite large, way to large to have everything crammed into one source file. So I am trying to separate the project into different files. I have four classes and I want to put each in its own separate source file.
What I did:
I moved all of the classes into their own files so now I have this
proj/GoogleChart.rb
proj/BarChart.rb
proj/PieChart.rb
proj/GroupedBarChart.rb
Now that they are in other files I am getting uninitialized constant GoogleChart (NameError) in all of my subclasses on the line where I inherit from GoogleChart, i.e.
require 'GoogleChart'
BarChart < GoogleChart
Can anyone tell me what is wrong?
Thanks
EDIT
Using ruby version 1.8.4
Also I have tried using the absolute path:
require 'C:/Documents and Settings/proj/GoogleChart.rb' and this is still producing a NameError
In Ruby 1.8.x, the . is part of your load path. So you should at least try to debug that by including something like:
puts $:
require 'GoogleChart'
class BarChart < GoogleChart
end
and load that in an IRB session:
Open the session in your directory proj.
Enter there require 'BarChart'
Look at the result.
For me it is:
c:\apps\ruby\test\proj>irb
irb(main):001:0> require 'BarChart'
C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/site_ruby/1.8
C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/site_ruby/1.8/i386-msvcrt
C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/site_ruby
C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/vendor_ruby/1.8
C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/vendor_ruby/1.8/i386-msvcrt
C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/vendor_ruby
C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/1.8
C:/Users/mliebelt/.pik/rubies/Ruby-187-p334/lib/ruby/1.8/i386-mingw32
.
=> true
So the require is successful for me, and the . is part of the path (as it should). As you can see, I am working with Ruby 1.8.7, I don't know if anything has changed since 1.8.4 that is relevant here.
So please describe exactly how you run your file:
Have you opened a shell to run the file?
What is the current working directory of that shell?
Do you run by double-clicking it?
It only works when you are in your proj directory and run there (with ruby in your shell path) ruby BarChart.rb.

Resources