How to delete a row from CSV file - ruby

I want to delete a row and write back to the file.
When I delete it deletes all contents of the CSV file.
products = {}
def menu
puts "#{'Item'.ljust(6)} #{'Description'.ljust(10)} #{'Price'.rjust(7)}"
puts '-' * 4 + ' ' + '-' * 11 + ' ' + '-' * 5
File.open('text.txt').readlines.each do |itemnumber|
puts itemnumber.gsub(/[,]/, ' ')
end
end
user_choice = 0
while user_choice !=8
puts ''
puts 'What would you like to do?'
puts '1: View all products.'
puts '2: Add a new product.'
puts '3: Delete a product.'
puts '4: Update a product.'
puts '5: View highest priced product.'
puts '6: View lowest priced product.'
puts '7: View sum of all products prices.'
puts '8: Exit.'
user_choice = gets.chomp.to_i
if user_choice == 1
menu
end
if user_choice == 2
puts ''
puts 'Enter new products description. '
new_products = gets.chomp
puts 'Enter new products price. '
price = gets.chomp.to_f
new_key = rand(100..999)
while products.has_key?(new_key)
new_key = rand(100..999)
end
puts "#{new_key},#{new_products},#{price}"
open('text.txt', 'a') { |newproduct|
newproduct.puts "#{new_key},#{new_products},#{price}"
}
end
if user_choice == 3
menu
puts ''
puts "What's the item number you wish to delete?"
item_num = gets.chomp
read_file = File.new('text.txt', "r+").read
write_file = File.new('text.txt', "w+")
read_file.each_line do |line|
write_file.write(line) unless line.include? item_num
end
end
What am I doing wrong? In the "delete" part of the program, I'm sure there are multiple things wrong.

Your delete is actually happening, but your currently running application is not aware of that yet.
You can check that by restarting the app and/or by looking at the text file.
To fix this, after writing to the file ends in the block, close the file so that the change is flushed:
read_file.each_line do |line|
write_file.write(line) unless line.include? item_num
end
write_file.close

Related

Why will this not iterate through the file like I want it to?

It will just output two blank lines to the screen when it should be printing the card id and the balance
I have completely re-written the code.
I have fiddled with that code for an hour
class RBC
def initialize
#args = ["Create a new card"]
#functions = ["create_rbc"]
puts "Do you have an RBC ID yet? Yes(0) No(1)"
hasrbc = gets.chomp.to_i
if hasrbc == 1
#balance = 5
create_rbc
else
login
end
end
def create_rbc
puts "\nGenerating your rbc\n\n"
puts "\nWelcome to your Ruby Binary Card(RBC)!\n\n"
puts "Your RBC will keep track of your RubyCredits(RC).\n"
puts "You will get paid RC for work apps, and pay for game apps.\n"
puts "If you lose track of your RBC ID, you can get a new one.\n"
puts "Doing this, however, will reset your balance to the default of $5\n\n"
puts "What is your name? Do first last\n"
#fullname = gets.chomp
#card_name = get_name_codec(#fullname)
#card_cipher = "#{rand(1..9)}#{rand(1..9)}#{rand(1..9)}#{rand(1..9)}#{rand(1..9)}#{rand(1..9)}#{rand(1..9)}#{rand(1..9)}#{rand(1..9)}#{rand(1..9)}"
#card_id = "#{#card_name} - #{#card_cipher}"
instance_variable_set("#Id#{#card_cipher}", #balance)
puts "Write down your RBC ID: #{#card_id}"
file = File.open("Cards.rbc", "w")
file.puts #card_id
file.puts #balance
end
end
def get_name_codec(name)
names = name.split(" ")
fname = names[0]
lname = names[1]
fchar = fname.split(//)
fcodec = "#{fchar[0]}#{fchar[1]}"
name_codec = "#{fcodec}#{lname}"
return name_codec
end
def login
#found = false
puts "What is your RBC Id"
input = gets.chomp
File.open("Cards.RBC", "r") do |f|
f.each_line do |line|
if input == "#{line}"
#card_id = line.to_s
#found == true
elsif #found == true
#balance = line.to_i
end
end
end
puts "#{#card_id}#{#balance}"
end
RBC.new
Then the Cards.RBC
TiLan - 1122632527
5
I want it to print the balance and card Id.
It should give me my card id and then the balance like this:
0000...etc
5
input = gets.chomp removes the newline off the input, but f.each_line does not. So input == "#{line}" is comparing, for example, "1234" with "1234\n".
Chomp the line as well.
input = gets.chomp
File.open("Cards.RBC", "r") do |f|
f.each_line do |line|
line.chomp!
if input == line
#card_id = line
#found == true
elsif #found == true
#balance = line.to_i
end
end
end
You can debug this sort of thing by printing the values with p. This will show them as quoted strings and show any special characters including newlines.
p line
p input

Ruby Hangman game, does not work when I enter the full word but only when I enter one letter

Run my code your ruby interpretor, to see my code. Afterwards, try to guess the full word. The program will tell you that your guess was correct but it doesn't end the game if you guess the entire word instead of each letter one by one.
I also want to add a Dictionary to my code to be able to play against the computer instead of with myself or a friend!
def clear_screen
return system('cls') if Gem.win_platform?
system('clear')
end
loop do
incorrect_guesses = 0
puts ''
puts 'Welcome to Hangman, Win or lose your life!'
puts ''
puts 'Choose Category: It can be anything you desire!'
player1_category = gets.chomp
puts ''
puts 'Player 1, Please enter your desired word'
secret_word = gets.chomp.downcase
clear_screen
correct_guess = ['-'] * secret_word.length
clear_screen
puts "The category is: #{player1_category}"
puts 'Player 2, Please enter your guess'
loop do
puts '_ ' * secret_word.length
player2_guess = gets.chomp.downcase
clear_screen
if secret_word.include? player2_guess
secret_word.each_char.with_index do |letter, i|
next unless letter == player2_guess
correct_guess[i] = letter
end
puts "The category is: #{player1_category}"
puts ''
print 'Guess the word: '
print correct_guess.join('')
puts ''
puts 'Correct. Keep trying!!'
puts ''
else
puts "The category is: #{player1_category}"
puts ''
print 'Guess the word: '
print correct_guess.join('')
puts ''
puts "The word doesn't contain that letter '#{player2_guess.upcase}'"
puts ''
incorrect_guesses += 1
end
puts "Incorrect Guesses: #{incorrect_guesses}"
puts ''
if incorrect_guesses == 6
puts ''
puts '|---+---+- '
puts '| |'
puts '| 0'
puts '| |\\'
puts '| /\\'
puts '-+----------'
puts "The Secret Word is '#{secret_word.capitalize!}'"
puts ''
break
end
next unless secret_word == correct_guess.join('')
puts ''
puts ' (#)'
puts ' ^\\|'
puts ' |/^'
puts '____|_____'
puts ''
puts 'You Win!'
puts ''
puts "You correctly guessed the word '#{secret_word.capitalize!}'"
break
end
end
I got to work with the following change to the next unless test:
if secret_word.include? player2_guess
secret_word.each_char.with_index do |letter, i|
next unless player2_guess.include? letter
correct_guess[i] = letter
end
You were comparing the entire entry to a single character. 't' != 'test'
As for a dictionary, the answer in this link should help
Your question is not super clear, but here are a few comments / answers:
Guessing the whole word: You could wrap your current if secret_word.include? player2_guess in another if that tests the length of the input. (This assumes all words are greater than 1 letter). The if statement should test if the user_input.length > 1. If so, evaluate whether the guess is the correct word, etc.
Adding a dictionary: Easiest was would be to hardcode an array of possible word values. If you want them to correspond to a category, you could make a hash like this {'category_1' => [word, word, word], 'category_2' => [word, word, word]}. Then you could pick a random value from the hash (category) and then a random value from the corresponding array.

When creating an inventory, how do I keep people from adding a negative number?

I am creating a very simple "Repository" as my first real ruby script. I have the sections created where people can create an item and starting value, but I cannot seem to nail down how to keep people from incrementing (or decrementing) by 0 or negative numbers.
My code to add is as follows:
class Item
attr_accessor :name, :count
def initialize (name,initCount )
#name=name.downcase
#count=initCount
end
def add(amount)
#count += amount
end
def sub(amount)
#count -= amount
end
end
def prompt()
puts #items.inspect
puts " (A)dd item\n (R)emove item\n (L)ist items\n (I)ncrease item\n (D)ecrease items\n (Q)uit "
select = [(print '?: '), gets.rstrip][1]
if (select.upcase=="A") then
puts "Add Item\nItem name"
name=[(print 'Name? : '), gets.rstrip][1]
puts "Initial Count"
count= [(print 'Count? : '), gets.rstrip][1]
#items.push(Item.new(name,count.to_i)) unless #items.index(#items.find { |l| l.name == name })
end
Any help is appreciated.
Consider organizing your code like this. I may have made a few errors, but you'll get the idea.
PROMPT_TEXT =
" (A)dd item
(R)emove item
(L)ist items
(I)ncrease items
(D)ecrease items
(Q)uit ?: "
ILLEGAL_PROMPT_RESPONSE_MSG =
"You can't enter that! What were you thinking??"
NEGATIVE_NUMBER_MSG =
"If I've told you once, I've told you a thousand times: NO NEGATIVE NUMBERS!"
NOT_NUMBER_MSG =
"If that's a number, it must be Roman, and they aren't allowed."
TRY_AGAIN_MSG = "Try again...
.
def prompt()
loop do
puts #items.inspect # What's this?
puts PROMPT_TEXT
gets.rstrip.upcase case
when "A"
break if add_item
when "R"
...
when "L"
...
...
when "Q" then return
else
puts ILLEGAL_PROMPT_RESPONSE_MSG
end
puts TRY_AGAIN_MSG
end
end
.
def add_item
puts "Add Item\nItem name"
print 'Name? : '
name = gets.rstrip
puts "Initial Count"
print 'Count? : '
count = gets.rstrip
unless count =~ /\d+/
if count =~ /-\s*\d+/
puts NEGATIVE_NUMBER_MSG
else
puts NOT_NUMBER_MSG
end
return false
end
#items.push...
true
end
Aside: the statement
name=[(print 'Name? : '), gets.rstrip][1]
brings to mind a word that begins with "abomin" and ends with "ation". :-)
class Item
attr_accessor :name, :count
def initialize (name,initCount )
raise if initCount<0
#name=name.downcase
#count=initCount
end
def add(amount)
raise if amount<0
#count += amount
end
def sub(amount)
raise if amount<0 || amount>#count
#count -= amount
end
end

Ruby Script Error

In the gets portion at the lower half of the program, the terminal is not asking me for input but automatically taking input. I am unable to understand how this is happenening.
The Code is:
puts "Welcome to my automatic file opener"
puts "Version - 2.0"
if ARGV[0] && ARGV[1] #to ensure Arguements are given as input
old_data = File.open(ARGV[0]).readlines
new_data = File.open(ARGV[1]).readlines
class Differentiator
def old_stuff
puts "the old files are:-"
puts old_data
end
def new_stuff
puts "The new files are:-"
puts new_data
end
def updated_list
puts "The newly added files are:-"
newly_added = new_data - old_data
puts newly_added
end
def deleted_list
puts "The deleted files are:-"
deleted_data = old_data - new_data
puts deleted_data
end
def stable_list
puts "The unchanged/stable files are:-"
unchanged_data = new_data - newly_added
puts unchanged_data
end
end#end of class
while true
puts "Choose your option:"
puts "1.Old Files of System"
puts "2.New Files of System"
puts "3.Added Files of System"
puts "4.Deleted Files of System"
puts "5.Stable Lists"
puts "6.Exit"
print " Please Choose your Output:-"
**option_method=gets.chomp.to_i**
filecase1 = Differentiator.new
if option_method == 1
filecase1.old_stuff
end
if option_method == 2
filecase1.new_stuff
end
if option_method == 3
filecase1.updated_list
end
if option_method == 4
filecase1.deleted_list
end
if option_method == 5
filecase1.stable_list
end
if option_method == 6
break
exit
end
if option_method != (1..6)
puts "Sorry,Wrong Input"
end
end
else
puts "The Right Method of Usage is : ruby <scriptname>.rb old_file new_file"; exit;
end
Because you have to use $stdin.gets otherwise it will read the files given in ARGV.
It is written in the man page http://www.ruby-doc.org/core-2.0/Kernel.html in the first line talking about gets

Help! check_in': undefined method `push' for nil:NilClass (NoMethodError)

Hi Im getting an core error which is really standard I suppose in Ruby but dont know what to make of it. I have a program that I have written. Its purpose is to register guests at a camping. You have a menu with 5 different options. 1. Checkin. When i do this I get a undefined method generateParkingLot' for #<Camping:0x10030a768> (NoMethodError)
When I choose Checkout I get a undefined local variable or methoddeparture' for Menu:Class (NameError).
So please i someone has a clue to my problem it would be great. I will here paste all my code. The code is separated in different files and I have used require for the different files. Here though I will paste all the code in one trace. Thankful for all help.
-Sebastien
require 'guest'
require 'parking_lot'
class Camping
attr_accessor :current_guests, :parking_lots, :all_guests, :staticGuests
def initialize(current_guests, parking_lots, all_guests, staticGuests)
#current_guests = Array.new()
# initiera husvagnsplatserna
#parking_lots = Array.new(32)
32.times do |nr|
#parking_lots[nr] = Parking_Lot.new(nr)
#staticGuests = Array[
Guest.new("Logan Howlett", "Tokyo", "07484822",1, #parking_lots[0]),
Guest.new("Scott Summers", "Chicago", "8908332", 2, #parking_lots[1]),
Guest.new("Hank Moody", "Boston", "908490590", 3, #parking_lots[2]),
Guest.new("Jean Grey", "Detroit", "48058221", 4, #parking_lots[3]),
Guest.new("Charles Xavier","Washington DC", "019204822",5, #parking_lots[4])
]
end
#all_guests = []
#staticGuests.each do |guest|
#current_guests[guest.plot.nr] = guest
#all_guests.push(guest)
end
end
def to_s
# creates an empty string
list = " "
# loop from 1 to 32
(1..32).each do |n|
if (!#current_guests[n-1].nil?)
list += #current_guests[n-1].to_s
else
# else adds the text "Vacant"
list += n.to_s + ": Vacant!\n"
end
return list
end
def generateParkingLot
randomNr = 1+rand(32)
# exists a guest at the (0-based) position?
if (!#current_guests[randomNr-1].nil?)
# if so generate a new figure
generateEmpty(array)
else
# returns the generated number
return randomNr
end
end
end
end
class Guest
attr_accessor :firstname, :lastname, :address, :phone, :departure
attr_reader :arrived, :plot
def initialize (firstName, lastName, address, phone, plot)
#firstName = firstName
#lastName = lastName
#address = address
#phone = phone
#arrived = arrived
#plot = plot
end
def to_s
"Personal information:
(#{#firstName}, #{#lastName}, #{#address}, #{#phone}, #{#arrived}, #{#departure}, #{#plot})"
end
end
require 'ruby_camping'
require 'camping_guests'
class Main
if __FILE__ == $0
$camping = Camping.new(#current_guests, #all_guests, #parking_lots,#staticGuests)
puts "\n"
puts "Welcome to Ruby Camping!"
while (true)
Menu.menu
end
end
end
require 'date'
require 'camping_guests'
require 'guest'
class Menu
def initialize(guests = [])
#camping = Camping.new(guests)
end
def self.menu
puts "---------------------------"
puts " Menu"
puts " 1. Checkin"
puts " 2. Checkout"
puts " 3. List current guests"
puts " 4. List all guests"
puts " 5. Exit\n"
puts ""
puts " What do you want to do?"
puts "---------------------------"
print ": "
action = get_input
do_action(action)
end
# fetches menu choice and returns chosen alternativ
def self.get_input
input = gets.chomp.to_i
while (input > 5 || input < 1) do
puts "Ooups, please try again."
input = gets.chomp.to_i
end
return input
end
def self.do_action(action)
case action
when 1:
check_in
when 2:
check_out
when 3:
puts $camping.current_guests
when 4:
puts $camping.all_guests
when 5:
puts "You are now leaving the camping, welcome back!"
exit
end
end
def self.check_in
puts "Welcome to the checkin"
puts "Please state your first name: "
firstName = gets.chomp
puts "Please state your last name:"
lastName = gets.chomp
puts "Write your address: "
address = gets.chomp
puts "and your phone number: "
phone = gets.chomp
puts "finally, your arrival date!"
arrived = gets.chomp
newPLot = $camping.generateParkingLot
newGuest = Guest.new(firstName, lastName, address, phone,arrived,$camping.parking_lots[newPLot-1])
$camping.current_guests[newPLot-1] = newGuest
#all_guests.push(newGuest)
puts "The registration was a success!! You have received the " + newPLot.to_s + "."
end
def self.check_out
puts "Welcome to checkout!"
puts $camping.all_guests
puts "State plot of the person to checkout!"
plot = gets.chomp.to_i
puts "Ange utcheckningsdatum: "
departureDate = gets.chomp.to_i
guest = $camping.current_guests[plot-1]
#departure = departure
guest.departure = departureDate
guestStayedDays = departureDate - guest.arrived
guest.plot.increase(guestStayedDays)
puts guest
$camping.current_guests[plot-1] = nil
end
end
class Parking_Lot
attr_accessor :nr
attr_reader :electricity_meter
def initialize (nr)
#nr = nr
#electricity_meter = 4000-rand(2000)
end
def increase_meter(days)
generatedUse = (10+rand(70))*days
puts "Increases the meter with " + generatedUse.to_s + " kWh."
#electricity_meter += generatedUse
end
def to_s
"Plot #{#nr+1} Electricity meter: #{#electricity_meter} kWh"
end
end
It looks (although I haven't tried this out) like some of your your 'end's are wrong.
The one which is causing your first error (generateParkingLot undefined) is that generateParkingLot is actually defined inside to_s, so you need an extra 'end' at the end of your to_s method.
As for the second error (departure not recognised), the folowing line in self.check_out is at fault:
#departure = departure
because there is no 'departure' variable. (Perhaps you meant DepartureDate?). I suspect there may be a few other issues with this code, but I'm afraid I don't really have time to check now.
One I noticed was that when you have
32.times do |nr|
#parking_lots[nr] = Parking_Lot.new(nr)
I think you might want to end that, either with an 'end' or curly brackets, e.g.
32.times do |nr|
#parking_lots[nr] = Parking_Lot.new(nr)
end
Although that would make your other blocks not match.. In general, just try and make sure your blocks are all defined properly (e.g. everything has a matching end).

Resources