Reputation: 55
I am having trouble outputting the contents of my hash to a file. The program is one that manages a list of student records, including their StudentID, first name, last name, Major, and catalog year. Once the user is finished adding records, it is then added to the hash.
Everything in the program works perfectly, except when I try running the quit_program function, it doesn't save the contents in the file. Additionally, i am not getting any errors, any ideas?
could it potentially not be working because it is having trouble with converting the text in my hash, which is alphanumeric, into the text file?
def quit_program()
puts "Save Changes? y/n"
@changes = gets().chomp
if @changes=="y"
@fh=File.open(@file_name, 'w')
@this_string=""
@sDB.each do |key, store_account_data| #line 50
puts "#{key}: #{store_account_data.join(',')}"
end
end
@fh.puts(@this_string)
@fh.close()
end
Upvotes: 1
Views: 1318
Reputation: 160551
Your question is missing essential input data, so there's no way to test our suggested changes.
Here's untested code I'd work from:
def quit_program
puts "Save Changes? y/n"
if gets.chomp.downcase == 'y'
File.write(
@file_name,
@s_db.map{ |k, v| "#{ k }: #{ v.join(',') }" }.join("\n")
)
end
end
Note:
@sDB
isn't a proper variable name in Ruby. We use snake_case, not camelCase for variables and method names. ItsAMatterOfReadability. Follow the convention or suffer the wrath of your team members the first time you have a code review.quit_program()
) or calls (gets()
) unless it's essential to tell the difference between a variable and a method invocation. You should also never name a variable the same as a method because it'll confuse everyone working on the code, so that should never be a consideration.@changes
) you use once and throw away, unless what you're doing is so complex you need to break down the operation into smaller chunks. And, if you're doing that, it'd be a really good candidate for refactoring into separate methods, so again, just don't.gets.chomp.downcase == 'y'
). It really irritates users to enter "y" and fail because you insisted on "Y".File.open
to create or write to a file, there's less visual noise to use File.write
. open
is great when you need to use various options for the mode but for plain text write
is sufficient.map
and join
, which coerces the data into an array of strings then into a single string.Upvotes: 1
Reputation: 26
The answer is given in the error message: undefined local variable or method 'sDB'
. (Which you have since removed from your question making the edited version next to impossible to answer.) Where and when is sDB
defined in your program? You are evidently attempting to quit before initializing it.
In any case it is not a good thing to be accessing instance variables directly inside other methods. You should use accessor (getter and setter) methods instead. That would have probably prevented this situation from biting you in the first place.
def sdb
@sDB ||= Hash.new
end
def sdb=( key, value )
sdb
@sDB[ key ] = value
end
. . .
You are not properly writing to a file even if @sDB
is defined. See Ruby - Printing a hash to txt file for an example.
Upvotes: 1
Reputation: 48599
it doesn't save the contents in the file.
The following is NOT how you write to a file:
puts "#{key}: #{store_account_data.join(',')}"
That is how you write to your terminal/console window.
And this code:
@this_string=""
@fh.puts(@this_string)
writes a blank string to the file.
Here is how you write to a file:
class Student
def initialize(sDB, filename)
@sDB = sDB
@filename = filename
end
def save_changes()
puts "Save Changes? y/n"
user_answer = gets().chomp
if user_answer == "y"
File.open(@file_name, 'w') do |f|
@sDB.each do |key, store_account_data| #line 50
f.puts "#{key}: #{store_account_data.join(',')}"
end
end
end
end
could it potentially not be working because it is having trouble with converting the text in my hash, which is alphanumeric, into the text file?
No. Here is a concrete example you can try:
data = {
"John" => ['a', 123, 'b', 456],
"Sally" => ['c', 789, 'b', 0]
}
File.open('data.txt', 'w') do |f|
data.each do |name, data|
f.puts "#{name}: #{data.join(',')}"
end
end
$ ruby myprog.rb
$ cat data.txt
John: a,123,b,456
Sally: c,789,b,0
Also, ruby indenting is 2 spaces--not 0 spaces or 3 spaces, or anything else.
Upvotes: 1
Reputation: 5773
You're not writing anything to the file. The string @this_string
is empty. You should do
@sDB.each do |key, store_account_data|
@fh.puts "#{key}: #{store_account_data.join(',')}"
end
Upvotes: 1