What I'm attempting to do in Ruby is the equivalent to PHP's include or require statement.
In PHP, when you include or require a file, any PHP code in the included file is executed and globally scoped variables can be used in the file that houses the include.
In Ruby, I have this code;
# include file snippet
config = {'base_url' => 'http://devtest.com/'}
# main file
Dir.foreach(BASE_ROOT_PATH + 'config') do |file|
if !(file == '.' || file == '..')
filepath = BASE_ROOT_PATH + 'config/' + file
load filepath
end
end
config.inspect
The problem I'm encountering is that when I run the main file, it always errors out with this error;
/home/skittles/devtest/bootstrap.rb:24:in `<top (required)>': undefined local variable or method `config' for main:Object (NameError)
from <internal:lib/rubygems/custom_require>:29:in `require'
from <internal:lib/rubygems/custom_require>:29:in `require'
from index.rb:27:in `<main>'
I know that it's pulling in the file because it's not throwing any errors.
I tried load & require, both with the same error. I tried config.inspect and puts config, still same error.
It's almost like the included file is not executing the code inside it. Is that what's going on or am I simply doing something wrong?
Thanks
config isn't a globally scoped variable - it's a local variable and local variable scope does not stretch across a require or load.
If you did want a global variable then you need to call it $config - the prefix denotes whether a variable is local (no prefix), global ($) or an instance variable (#). A constant might also be appropriate.
Related
I have two files person.rb and contact_info.rb and the person.rb file contains a class, and the contact_info.rb file contains a module. When i do load 'person.rb' in irb this works fine when load 'contact_info.rb' is at the top of this file.
When I switch this to require 'contact_info.rb' at the top of the person.rb file, and in irb do require 'person.rb' I get an error (i've included the error at the bottom of this text and it's using a completely different file path.
I've googled some solutions such as using './person.rb' and require_relative 'person' but these don't work either.
I've simplified the code within files to make things easier.
Any help would be awesome.
CODE IN THE person.rb FILE
require 'contact_info.rb'
class Person
include ContactInfo
end
CODE IN THE contact_info.rb FILE
module ContactInfo
#some code
end
ERROR MESSAGE THAT I'M GETTING - when I type in require 'person.rb' in irb.
**note - when i drag the file into the command line the file path is /Volumes/New\ Passport/All\ Creative/Ruby/module_folder_tut/person.rb
LoadError: cannot load such file -- person.rb
from /Users/paulknight/.rvm/rubies/ruby-2.4.1/lib/ruby/site_ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from /Users/paulknight/.rvm/rubies/ruby-2.4.1/lib/ruby/site_ruby/2.4.0/rubygems/core_ext/kernel_require.rb:55:in `require'
from (irb):1
from /Users/paulknight/.rvm/rubies/ruby-2.4.1/bin/irb:11:in `<main>'
Current directory in NOT on the ruby search path by default. Add it to $: and everything will be fine (assuming you are launching irb from the directory where person.rb is located):
$: << "."
require "person.rb"
More detailed info.
I have many directories with generically named txt files inside. I want to make copies of the txt files, rename them according to the containing directory of each, then move them to the parent directory (that being the directory that holds the directories that hold the original txt files, designated "txts" in the script below). I want to retain the original txt files with their original names in their original directories as well so that nothing within the original directories changes.
I have an old script that I think achieved (some of) my goals once, perhaps moving instead of copying the original txt files, but I'm unable to run it successfully now:
require 'find'
require 'fileutils'
Find.find("txts") do |path|
if FileTest.directory?(path)
next
end
ret = path.scan(/.*txts\/([^\/]+)\/.*/)
name = ret[0].to_s + ".txt"
FileUtils.mv(path, name)
end
Years ago a friend wrote this and ran it from within a unix environment with success. When I run it now, an enormous number of errors are returned. I'm using Ruby 2.2.2 and it's entirely possible there's a placeholder somewhere that I'm too newbish to recognize, or perhaps something changed from the older version of FileUtils... I truly have no idea and am afraid I've been unable to turn up any answers with my neophyte skills.
And so I appeal to you...
Edit: Here's the error message:
C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1328:in `stat': Invalid argument # rb_file
_s_stat - ["may2013"].txt (Errno::EINVAL)
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1328:in `lstat'
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1247:in `exist?'
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:519:in `block in mv'
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1570:in `block in fu_each_src
_dest'
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1586:in `fu_each_src_dest0'
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1568:in `fu_each_src_dest'
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:516:in `mv'
from extracttxt.rb:12:in `block in <main>'
from C:/Ruby22/lib/ruby/2.2.0/find.rb:48:in `block (2 levels) in find'
from C:/Ruby22/lib/ruby/2.2.0/find.rb:47:in `catch'
from C:/Ruby22/lib/ruby/2.2.0/find.rb:47:in `block in find'
from C:/Ruby22/lib/ruby/2.2.0/find.rb:42:in `each'
from C:/Ruby22/lib/ruby/2.2.0/find.rb:42:in `find'
from extracttxt.rb:6:in `<main>'
The error message shows that ret[0] is the array [ "may13" ], so ret[0].to_s + ".txt" evaluates to the string ["may13"].txt. I'm not sure, but it's possible the behavior of String#scan changed in Ruby 1.9 or 2.0, so it returns an array of arrays when captures are present, whereas before it returned an array of strings.
Something like this ought to solve the problem:
require 'find'
require 'fileutils'
Find.find("txts") do |path|
if FileTest.directory?(path)
next
end
if path =~ %r{txts/([^/]+)/}
FileUtils.cp(path, "#{$1}.txt")
end
end
If you want to match by file extension you could either add it to the Regexp above (e.g. %r{txts/([^/]+)/.+\.txt$}) or you could use Dir[] (a.k.a. Dir.glob) e.g.:
require 'dir'
require 'fileutils'
Dir['txts/**/*.txt'].each do |path|
next if FileTest.directory?(path) ||
next unless path =~ %r{txts/([^/]+)/}
FileUtils.cp(path, "#{$1}.txt")
end
I don't know if there will be any performance difference, but it might be worth trying.
I'm trying to reference a file to write to it using RubyMine and I'm having trouble figuring it out. When using the full path, the code errors out while running it with RubyMine.
When I use the same code and run it in terminal, the code works fine using the command:
ruby studio_game players.csv
How can I get the file to be recognized without having to designate the full path in RubyMine?
Erring Code:
require_relative 'player'
require_relative 'game'
player1 = Player.new("moe")
player2 = Player.new("larry", 60)
player3 = Player.new("curly", 125)
knuckleheads = Game.new("Knuckleheads")
knuckleheads.load_players(ARGV.shift || 'players.csv')
Error message:
/Users/MNickey/.rvm/rubies/ruby-1.9.3-p448/bin/ruby -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) "/Users/MNickey/RubymineProjects/PragmaticStudio/Stooges Game/studio_game"
/Users/MNickey/RubymineProjects/PragmaticStudio/Stooges Game/game.rb:83:in `readlines': No such file or directory - players.csv (Errno::ENOENT)
from /Users/MNickey/RubymineProjects/PragmaticStudio/Stooges Game/game.rb:83:in `load_players'
from /Users/MNickey/RubymineProjects/PragmaticStudio/Stooges Game/studio_game:9:in `<top (required)>'
from -e:1:in `load'
from -e:1:in `<main>'
knuckleheads.load_players(ARGV.shift || 'players.csv') is almost certainly what is causing the problem. Unless you have configured the launcher for the script with a command line argument, ARGV will be empty and you will be getting plain-old 'players.csv' as the result.
I'm pretty certain you are running the script with an argument when you run it in the command line.
To set a command line parameter in RubyMine, go to Run / Edit Configurations, find the launch configuration for your script, and add the path to your csv file to the Script Arguments input box.
So I'm making this project in Ruby, and I copied this code from somewhere and It's not working.
Code:
dirname = File.dirname("C:/ProgramFiles/RubyLists")
require 'fileutils'
unless File.directory?(dirname)
File.mkdir(dirname)
end #This block will make the directory.
print("Mk. Worked.")
Error:
C:/Users/User/RubymineProjects/rubylists/main.rb:6:in `<top (required)>': undefined method `makedir' for File:Class (NoMethodError)
from -e:1:in `load'
from -e:1:in `<main>'
If you need anymore info let me know and I will provide it if I can. Thanks!
FileUtils::mkdir exist, not File::mkdir.
Thus change File.mkdir(dirname) to FileUtils.mkdir(dirname).
Write your code :-
dirname = "C:/ProgramFiles/RubyLists"
require 'fileutils'
unless Dir.exist?(dirname)
FileUtils.mkdir(dirname)
end #This block will make the directory.
print("Mk. Worked.")
Since you're using FileUtils you can use mkdir
FileUtils.mkdir("a/b/c")
though if any of the parent folders don't exist it would just crash. I typically use mkdir_p since it recursively creates directories as needed (unless I want it to crash, for example if the folder names were wrong)
# function for create folder
def createFolder(folderName)
#folderName=folderName
if File.directory?(#folderName)
return "The Folder "+#folderName+" already exist"
else
Dir.mkdir(#folderName,0700)
return "Created"
end
end
to call it just type
createFolder('folderName')
Can a require execute a locally defined function? I guess the easiest way to describe what I need is to show an example.
I'm using ruby 1.9.3, but solutions for 1.8 and 2.0 are also welcome.
I have a file main.rb as the following:
class Stuff
def self.do_stuff(x)
puts x
end
require_relative('./custom.rb')
do_stuff("y")
end
And also have a file custom.rb in the same folder, with the following content:
do_stuff("x")
Running main.rb, I have following output:
/home/fotanus/custom.rb:1:in `<top (required)>': undefined method `do_stuff' for main:Object (NoMethodError)
from main.rb:5:in `require_relative'
from main.rb:5:in `<class:Stuff>'
from main.rb:1:in `<main>'
Note that without the require, the output is y.
I'm not sure if it is the best solution but using eval should do the trick.
class Stuff
def self.do_stuff(x)
puts x
end
eval(File.read('./custom.rb'))
do_stuff("y")
end
The output will be:
pigueiras#pigueiras$ ruby stuff.rb
x
y
In C, #include literally drops the code as-is into the file. require in Ruby is different: it actually runs the code in the required file in its own scope. This is good, since otherwise we could break required code by redefining things before the require.
If you want to read in the contents of a script and evaluate it in the current context, there are methods for doing just that: File.read and eval.