My gem cannot see a dictionary text file, I cannot get the path - ruby

I wrote an implementation of the hangman game. (It is played on the terminal). The game is working fine but I usually have some problems getting my program to open a dictionary txt file from where the word will be generated. Below is my code for generating the word
def word_generator(min, max)
words = File.open("../dictionary.txt"), "r").readlines.map!(&:chomp)
level_words = words.select { |i| i.length >= min && i.length <= max }
random_index = rand(level_words.length)
#game_word = level_words[random_index]
end
This approach works fine when I play my game locally and the dictionary text file is just one directory level away from my ruby file. Here is the problem:
When I package the project as a gem, and install it. It will throw this error in initialize': No such file or directory # rb_sysopen /Users/andeladev/Desktop/paitin_hangman/bin/dictionary.txt (Errno::ENOENT). It will only run fine when I put the text file in the present working directory of the terminal.
How do I go about writing the path in the argument passed to File.open that will tell the program to look for the file in the gem path rather than the present working directory.

Try this:
file_name = File.join(File.dirname(File.expand_path(__FILE__)), '../dictionary.txt')
words = File.open(file_name, "r").readlines.map!(&:chomp)

Related

Opening a Text File in Ruby

I am trying to create a program that will count the word frequency within a text file that I have created. I have a text file titled moms_letter.txt and this is my code:
word_count = {}
File.open("moms_letter.txt", "r") do |f|
f.each_line do |line|
words = line.split(' ').each do |word|
word_count[word] += 1 if word_count.has_key? word
word_count[word] = 1 if not word_count.has_key? word
end
end
end
puts word_count
The problem I am getting is when I go to run the file, I get the error:
there is no such file or directory - moms_letter.txt (Errno: : ENOENT)
Not quite sure why this is occurring when I have the text file created.
Any help is appreciated.
I am also newbie in Ruby, so thanks for the patience.
You must be executing your program from outside the directory where your moms_letter.txt file resides. You need to use an absolute path to open your file. Or, execute your program always from the directory where the .txt is. So, instead of using "moms_letter.txt" go with "complete/path/to/file/moms_letter.txt".
I'm fairly new to Ruby too, but have worked with text files a bit recently. It may seem like an obvious question, but is the text file you're trying to open in the same directory as your .rb file? Otherwise you'll need to include the relative path to it.
For troubleshooting sake, try File.new("temp.txt", "w") and then File.open("temp.txt", "r") to see if that works. Then you'll know if it's an issue with your code or with the txt file you're trying to access.
Also using File.exists?("moms_letter.txt") will help you determine whether you can access that file from within your .rb script.
Hope that helps!

Can't use io.open in home directory - Lua

I'm writing a Mac OS program, and I have the following lines:
os.execute("cd ~/testdir")
configfile = io.open("configfile.cfg", "w")
configfile:write("hello")
configfile:close()
The problem is, it only creates the configfile in the scripts current directory instead of the folder I have just cd' into. I realised this is because I'm using a console command to change directory, then direct Lua code to write the file. To combat this I changed the code to this:
configfile = io.open("~/testdir/configfile.cfg", "w")
However I get the following result:
lua: ifontinst.lua:22: attempt to index global 'configfile' (a nil value)
stack traceback:
ifontinst.lua:22: in main chunk
My question is, what's the correct way to use IO.Open to create a file in a folder I have just created in the users home directory?
I appreciate I'm making a rookie mistake here, so I apologise if you waste your time on me.
You have problems with ~ symbol. In your os.execute("cd ~/testdir") is the shell who interprets the symbol and replaces it by your home path. However, in io.open("~/testdir/configfile.cfg", "w") is Lua who receives the string and Lua doesn't interprets this symbol, so your program tries to open a file in the incorrect folder. One simple solution is to call os.getenv("HOME") and concatenate the path string with your file path:
configfile = io.open(os.getenv("HOME").."/testdir/configfile.cfg", "w")
In order to improve error messages I suggests you to wrap io.open() using assert() function:
configfile = assert( io.open(os.getenv("HOME").."/testdir/configfile.cfg", "w") )

in `initialize': string contains null byte Ruby

I wrote the following code on my desktop and it worked fine. I downloaded it on my laptop, downloaded ruby (v1.9.3), and tried to run it but got the following error. I'm pretty sure it has to do with Ruby being used for the first time but never got this problem on my desktop when I first ran Ruby.
C:/Users/Downloads/vscript.rb:18:in 'initialize': string contains null byte (ArgumentError)
from C:/Users/Downloads/vscript.rb:18:in 'open'
from C:/Users/Downloads/vscript.rb:18:in 'main'
Line 18 is the File.open line:
File.open("filename", "r") do |f|
# Do while there are characters in the text file
f.each do |line|
# Checks to see if any parts in file match the regex and inform the user
if x = line.match(/\d\.\d\.\d{4}\.\d/)
puts "#{x} was found in the file."
end
end
end
Figured it out. When I originally wrote the code the filename had /'s separating the folders. When I downloaded the file on my laptop, I copied its new directory from the address bar which uses \'s. Changed that and it works fine now.

Can't get File Tail working

Out of curiosity I tried file-tail ruby library to see how it works with ruby code. But, the code doesn't seem to be working.
Here is what I tired(logger.rb):
$:.unshift File.dirname(__FILE__)
filename = 'logger.log'
require "file-tail"
File.open(filename) do |log|
log.extend(File::Tail)
log.interval = 10
log.backward(10)
log.tail { |line| puts line }
end
My logger.log file is in the same directory. Now, when I run: $ ruby logger.rb I see the last 10 lines from my log, but when I open logger.log file append some log data to it, the console doesn't show any progress. I mean it doesn't output the new log I appended.
I thought there may be in an issue with this. So, I tried inheriting and including the File::Tail in the inherited class, like this:
$:.unshift File.dirname(__FILE__)
filename = 'logger.log'
require "file-tail"
class FileTail < File
require "file-tail"
include File::Tail
end
log = FileTail.new(filename)
log.interval = 10
log.backward(10)
log.tail { |line| print line }
However this behaves the same way!!
Any pointers?
I am running on MAC OC X 10.8.5 with ruby-2.0.0-p353 installed.
Also, please let me know if anybody has implemented web version of tail in Ruby?
My Bad. This works when I closed all streams of my logger file. I'd opened the file in my ruby code but, didn't close the file stream. Maybe that's why I didn't see any log output on my console using the file-tail.
So, make sure you close all streams of the log/text file you're running with file-tail program.

Error reading local file in Sinatra

I'm trying to write a Sinatra app that reads in a list from a file, and then spits back a random item from that list.
I'm having trouble figuring out the path to the file to read it, though. Sinatra says 'no such file or directory' when I try to load an item in my browser:
Errno::ENOENT at /wod
No such file or directory - http://localhost:4567/listing.txt
Here is the code:
require 'sinatra'
#list
get /item
puts read_list[rand(#list.size)]
end
def read_list
File.open('listing.txt', 'r').readlines
end
I have the file in /public, which the Sinatra README says is the default location for hosting static files. Furthermore, if I put it in /public I can navigate to localhost:4567/listing.txt and read the file in the browser.
A couple things I noticed:
get /item
isn't correct, it should be:
get '/item' do
If you start your code inside the same directory the Ruby code is in, the current working-directory will be ".", which is where Ruby will look when trying to:
File.open('listing.txt', 'r').readlines
Ruby will actually use './listing.txt' as the path. That's OK if you manually launch the code from the root directory of the application, but that doesn't work well if you try to launch it from anywhere else.
It's better to be explicit about the location of the file when you're actually trying to load something for use with a web server. Instead of relying on chance, there are a couple things you can do to help make it more bullet-proof. Consider this:
def read_list
running_dir = File.dirname(__FILE__)
running_dir = Dir.pwd if (running_dir == '.')
File.open(running_dir + '/public/listing.txt', 'r').readlines
end
File.dirname gets the path information from __FILE__, which is the absolute path and name of the current file running. If the application was started from the same directory as the file, that will be ., which isn't what we want. In that case, we want the absolute path of the current working-directory, which Dir.pwd returns. Then we can append that to the path of the file you want, from the root of the application.
You'll need to do File.read('public/listing.txt', 'r') to get what you want here.
File.open isn't part of Sinatra and doesn't know to look in a specific place for static files, so it just looks in the current working directory.

Resources