Cant add data to file - ruby

file_1 = File.open('Data_family.txt', 'r')
user1 = go
while user1 != "stop"
print "whould you like to create: "
user1 = gets.chomp
print "what is your relation: "
relation = gets.chomp
file_1.syswrite "this is your " + relation
file_1.syswrite "\n"
end
file_1.close
am am confused as to why by block does not run. I whould like to create a family tree data base yet it will not allow me to add data to the file i opened

I think you're trying to do something like:
#!/usr/bin/eval ruby
File.open('Data_family.txt', 'w') do |file_1|
loop do
print "Who would you like to create: "
user1 = gets.chomp
break if user1 == "stop"
print "what is your relation: "
relation = gets.chomp
file_1.puts "this is your " + relation
end
end #File autocloses at the end of the block

Related

Ruby - Create a class with a file as a variable - possible?

I need to create a program in which the user can take different tests. As i dont want to copy paste my code all over for every test, i have tried to setup a class for that purpose - but i have problems with this class.
Error message = undefined variables or method in 'display_test'
I have predefined som test as a .txt file
I want to choose the file in the class depending on what the user answer - is that possible?
Class code:
class Test
#correct_answers = 0
def display_question( question, options, answer )
puts question
options.each_with_index { |option, idx| puts "#{ idx + 1 }: #{ option
}" }
print 'Answer: '
reply = gets.to_i
if answer == reply
puts 'Correct!'
#correct_answers += 1
puts "#{#correct_answers}"
else
puts 'Wrong. The correct answer was: ' + answer.to_s
end
end
def display_test()
f = File.new(userinput, 'r')
while ! (f.eof?) #logikken til at splitte
line = f.gets()
question = line.split("|")
question[1] = question[1].split(";")
display_question question[0], question[1], question[2].to_i
end
end
display_test
puts "________________________________________________________"
puts "Total score:"
puts "You've got" + " #{#correct_answers}" + " correct answers!"
Before hand i have used ("geografitest.txt") instead of username in the File.new so it looked like this:
f = File.new('geografitest.txt','r')
But now i am trying to let the user decide what test to take.
I am very new to ruby, so please bear with me.
I have tried to do it this way, which obviously is not working.
puts "Which test do you want to take?"
select = 0
while (select != 3)
puts "Press 1 to take Geografi test."
puts "Press 2 to take Math test."
puts "Press 3 to take Religion test."
puts "Press 3 to exit"
select = gets.chomp.to_i
if (select == 1)
gets.chomp = userinput
userinput =`geografitest.txt`
echo $userinput
end
if (select == 2)
gets.chomp = userinput
userinput =`matematiktest.txt`
echo $userinput
end
if (select == 3)
gets.chomp = userinput
userinput =`religionstest.txt`
echo $userinput
end
if (select > 4)
puts "Not a correct selection"
elsif (select == 4)
puts "Goodbye"
end
end
abort
So my questions is now;
How can i make the user choose what test to take? Can i make a variable instead of the textfile as i have tried, but in a different way? Or is there a smarter way?
And in what way is my class wrong and how do i fix it? I know its not the way to make it, but i simple cant get my head around how to make it right.
Please help a rookie out.
Cheers!
You can pass file as dependency to you Test class based on user input with object constructor. Something like this
class Test
attr_reader :correct_answers_count
def initialize(file)
#file = file
#correct_answers_count = 0
end
#other code goes here
end
loop do
case user_input = gets.chomp
when '1'
file_name = 'some_file1'
when '2'
file_name = 'some_file1'
when '3'
break
else
puts 'wrong variant'
end
test = Test.new(File.new(file_name, 'r'))
test.display
end

Ruby | Trying to check password by comparing to a file

I have some troubles with my code using Ruby. its just for a terminal program, so no website or anything.
In my code I Will have the user create a login. Then I will have the user to login, but I cant seem to figure out how to check if password or username is correct.
The program should compare whatever the user types in as a username/password with the file (userdatabase) - I think i got that right.
Now I am trying to stop the user if the input is not found in the user database, using a while loop, but i cant seem to make that work.
Code:
puts "What will be your user name?"
username = gets.chomp
puts "What will be your password?"
password = gets.chomp
puts "Please repeat your password."
passwordsafe = gets.chomp
f = File.new("student.txt", "w+")
f.puts username + ";" + password + ";" + passwordsafe
f.close
puts "well done, you have created a new user."
lines = IO.readlines("student.txt")
lines.each{|line| print(line)}
puts "now you need to login."
puts "What is your username?"
username = gets.chomp
File.open("student.txt") do |f|
f.any? do |line|
while line.include?(username)
end
end
elsif puts "Sorry your username was incorrect"
end
#lines = IO.readlines("student.txt")
#lines.each{|line| (line)}
puts "what is your password?"
password = gets.chomp
The while is unnecessary.
The username check currently like this:
File.open("student.txt") do |f|
f.any? do |line|
while line.include?(username)
end
end
Could be like this:
File.open("student.txt").each_line.any? do |line|
line.include?(username)
end
Or collapsed to a single line like this:
File.open("student.txt").each_line.any?{ |l| l.include?(username) }
Check the docs on the any? method to make sure you understand what it's expecting: http://ruby-doc.org/core-2.4.2/Enumerable.html#method-i-any-3F
As for the rest of the syntax errors, I'll leave those up to you ;)

Deleting a row from a CSV file with Ruby

I've seen similar answers to this question but I think I need something more specific to my code. Basically I've called the row from the CSV file but now I need to delete the called row. Sounds simple as I write this yet here I am asking you all for help. I know there is a lot of code here but I figured the more there is the more easier you will be able to understand the context. Apologies if there is too much noise in the code.
def delete_user_menu
puts "============================================"
delete_users_active_list
puts " "
puts "Please type in the name of the user you wish to eradicate: "
print "> "
eradicate(gets.chomp)
end
def eradicate(delete_input)
delete_row = delete_authentication(delete_input)
if delete_row
puts "Are you sure you want to delete #{delete_input} from the database?"
puts "[y]es or [n]o"
print "> "
delete_answer = gets.chomp
if delete_answer == "y"
delete_user
after_deletion_menu
elsif delete_answer == "n"
puts "Close call! Taking you back to main menu."
sleep 2
admin_main_menu
else
puts "Input not recognised. Please try again."
eradicate(delete_input)
end
else
puts "User not recognized. Please try again."
sleep 1
delete_user_menu
end
end
def delete_user
# this is where the delete user function needs to go
after_deletion_menu
end
def after_deletion_menu
puts " "
puts "User deleted! What would you like to do now?"
puts "1. Delete another user"
puts "2. Back to main menu"
print "> "
after_deletion_choice = gets.chomp
if after_deletion_choice == "1"
delete_user_menu
elsif after_deletion_choice == "2"
admin_main_menu
else
puts "Input not recognized. Please try again."
after_deletion_menu
end
end
def delete_users_active_list
CSV.foreach("./users.csv", headers: true) do |row|
username = row['username']
puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
puts "Username: #{username}"
end
end
def delete_authentication(username)
CSV.open('users.csv', headers: true).find { |row| row['username'] == username }
end
I've had a look at this question How to remove a row from a CSV with Ruby
but I don't fully understand the answers, hence why I'm here. Any help is much appreciated.
I looked at the link. First, they are reading the entire csv file into table:
table = CSV.table(#csvfile)
then deleting the row from table:
table.delete_if do |row|
row[:foo] == 'true'
end
Finally, they are completely replacing the original file with the new table minus the row:
File.open(#csvfile, 'w') do |f|
f.write(table.to_csv)
end
This is generally how you have to do this kind of operation when you are dealing with a file. It's not like a database.
EDIT - in your case:
delete_user(delete_input)
...
def delete_user(user)
...
table.delete_if { |row| row[:username] == user }
...

Converting file to string and replacing string text with user input

I need to replace placeholders NOUN, VERB, ADJ, and ADV in a file solution09.txt with user input.
Madlib solution09.txt:
One day I was watching my son [ADV] play with his [NOUN]. He was pretending the [NOUN] were [ADJ]. After a few minutes he was pretending to [VERB], because one of the [NOUN] drove away. When i asked him about it he [ADV] said, umm it's funny when [NOUN] [VERB] because [NOUN] can't really [VERB].
I think I successfully put the file into a string, but I have to read the string, and replace the placeholders with user input. Once I replace, I need to output the new madlib. I'm getting the user input into variables, but I'm not sure how to correctly replace the placeholder with the users input.
Current code:
file = File.open("solution09.txt", "r")
contents = file.read
puts "Enter a noun: "
noun = gets.chomp
puts "Enter a verb: "
verb = gets.chomp
puts "Enter an adjective: "
adj = gets.chomp
puts "Enter an adverb: "
adv = gets.chomp
if file.include?('NOUN')
file1= file.gsub("[NOUN]", noun, "[VERB]", verb, "ADJ", adj, "ADV", adv)
end
You can also build a replacement hash:
filename = "solution09.txt"
contents = File.read(filename)
replacements = {}
puts "Enter a noun: "
replacements['[NOUN]'] = gets.chomp
puts "Enter a verb: "
replacements['[VERB]'] = gets.chomp
puts "Enter an adjective: "
replacements['[ADJ]'] = gets.chomp
puts "Enter an adverb: "
replacements['[ADV]'] = gets.chomp
And pass it to gsub:
contents.gsub(Regexp.union(replacements.keys), replacements)
Regexp.union creates a pattern that matches any of the given keys.
Your code should look like
filename = "solution09.txt"
contents=File.read(filename)
puts "Enter a noun: "
noun=gets.chomp
puts "Enter a verb: "
verb=gets.chomp
puts "Enter an adjective: "
adj=gets.chomp
puts "Enter an adverb: "
adv=gets.chomp
if contents.include?('NOUN')
{ "\[NOUN\]" => noun,
"\[VERB\]" => verb,
"\[ADJ\]" => adj,
"\[ADV\]" => adv
}.each do |key, value|
contents.gsub!(key, value)
end
File.open(filename, "w") { |f| f << contents }
end
You need separate operation for read and write. There are other ways to do this
You can see how to do with single file pointer https://stackoverflow.com/a/10173112/1380263
You can also use ruby methods which interact with shell and use sed command (system, backticks, peopen)
Really depends on what suits your situation the best
file = File.read("solution09.txt")
.gsub(/\[(NOUN|VERB|ADJ|ADV)\]/) do
part = case $1
when "NOUN" then "a noun"
when "VERB" then "a verb"
when "ADJ" then "an adjective"
when "ADV" then "an adverb"
end
puts "Enter #{part}: "
gets.chomp
end

Ruby mulitple conditional statment write to same file twice?

I am trying to create a find and replace script in ruby. But I cannot figure out how to write to the same file twice when there are two conditions matched (2 different regex patterns are found and need to be replaced in the same file) I can get it to provide 2 copies of the file concatonated with only changes made from one condition in each.
Here is my code (Specifically pattern3 and pattern4):
print "What extension do you want to modify? "
ext = gets.chomp
if ext == "py"
print("Enter password: " )
pass = gets.chomp
elsif ext == "bat"
print "Enter drive letter: "
drive = gets.chomp
print "Enter IP address and Port: "
ipport = gets.chomp
end
pattern1 = /'Admin', '.+'/
pattern2 = /password='.+'/
pattern3 = /[a-zA-Z]:\\(?i:dir1\\dir2)/
pattern4 = /http:\/\/.+:\d\d\d\d\//
Dir.glob("**/*."+ext).each do |file|
data = File.read(file)
File.open(file, "w") do |f|
if data.match(pattern1)
match = data.match(pattern1)
replace = data.gsub(pattern1, '\''+pass+'\'')
f.write(replace)
puts "File " + file + " modified " + match.to_s
elsif data.match(pattern2)
match = data.match(pattern2)
replace = data.gsub(pattern2, 'password=\''+pass+'\'')
f.write(replace)
puts "File " + file + " modified " + match.to_s
end
if data.match(pattern3)
match = data.match(pattern3)
replace = data.gsub(pattern3, drive+':\dir1\dir2')
f.write(replace)
puts "File " + file + " modified " + match.to_s
if data.match(pattern4)
match = data.match(pattern4)
replace = data.gsub(pattern4, 'http://' + ipport + '/')
f.write(replace)
puts "File " + file + " modified " + match.to_s
end
end
end
end
f.truncate(0) makes things better but truncates the first line since it concatonates from the end of the 1st modified portion of the file.
Try writing file only once after all substitutions:
print "What extension do you want to modify? "
ext = gets.chomp
if ext == "py"
print("Enter password: " )
pass = gets.chomp
elsif ext == "bat"
print "Enter drive letter: "
drive = gets.chomp
print "Enter IP address and Port: "
ipport = gets.chomp
end
pattern1 = /'Admin', '.+'/
pattern2 = /password='.+'/
pattern3 = /[a-zA-Z]:\\(?i:dir1\\dir2)/
pattern4 = /http:\/\/.+:\d\d\d\d\//
Dir.glob("**/*.#{ext}").each do |file|
data = File.read(file)
data.gsub!(pattern1, "'#{pass}'")
data.gsub!(pattern2, "password='#{pass}'")
data.gsub!(pattern3, "#{drive}:\\dir1\\dir2")
data.gsub!(pattern4, "http://#{ipport}/")
File.open(file, 'w') {|f| f.write(data)}
end

Resources