Can you include `gets.chomp` in a variable with a prompt? - ruby

I am wondering if it is possible to include both a prompt character and gets.chomp in a variable. I can do:
prompt = "> "
puts prompt
input = gets.chomp
but is there a way to put both of them in a single prompt variable so that I don't need to type input = gets.chomp when I type puts prompt?

I used to always use the highline gem
require 'highline/import'
name = ask "whats your name"

You could wrap them in a method:
def ask_for_input
prompt = "> "
puts prompt
gets.chomp
end
input = ask_for_input # both prints a prompt and reads input

You can create your own gets method in the Kernel module :
module Kernel
def my_gets
gets.chomp
end
end
input = my_gets
print(input)

Related

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 ;)

A basic "Helper" program not working as expected

I'm making a basic "Helper" program..
Anyway here's the code:
def sayHelp()
puts "------------List of help and commands-------------"
puts "Help-- Shows a list of commands."
puts "Start [PROGRAM] (PROGRAM ARGS)-- Starts the specified program."
return true
end
version = "1.0"
ccommand = ""
puts "Welcome to RubyBot " + version + "."
puts "------------------------------------"
sleep(3)
system "clear" or system "cls"
puts "Enter \"help\" for a list of commands."
puts "Please enter a command: "
ccommand = gets
if ccommand == "help"
sayHelp()
else
puts "Not right bro"
end
I go ahead and run this and enter help but it just chucks Not right bro up at me.. What am I doing wrong?
ccommand = gets
The string returned by gets has a trailing new line character, remove it and it will work:
ccommand = gets.chomp

Why can't I use `filename.open' instead of `open(filename)'?

In this piece of code which lets you read a file in the terminal, why do you need to use open(filename) rather than filename.open?
filename = ARGV.first
txt = open(filename)
puts "Here's your file #{filename}:"
print txt.read
print "Type the filename again: "
file_again = $stdin.gets.chomp
txt_again = open(file_again)
print txt_again.read
You cant use filename.open, because filename is a String and method open is not defined in String
Use File#open
File.open(filename)
File.open("file")
opens a local file and returns a file object. Here File#open is a method of File class.
open("file")
is actually Kernel#open and looks at the string to decide what to do with it.
Trivializing things:
File.open("file") is telling Ruby specifically to open a file.
In case of open("file") Ruby examines the string "file" to determine what type it is (here a file) and open corresponding type else throws appropriate error.
Ruby has a class for dealing with paths in an object-oriented way: Pathname
require 'pathname'
loop do
print 'Enter filename: '
pn = Pathname(gets.chomp)
if pn.file?
puts "Here's your file '#{pn}':", pn.read
elsif pn.exist?
puts 'That is not a file.'
else
puts 'File does not exist.'
end
end

How would I access a key from a hash that is within an array that is within a text file in ruby?

I'm trying to create an if/else statement that compares a user's input against all the name keys within a hash that's stored with a text file. How would I write this?
user_accts is the array.
Update of full if/else statement:
elsif choice == "2"
puts "====== NEW CUSTOMER ======"
puts "Choose a username:"
prompt; login_name = gets.chomp
#file.open("cust_accts.txt", "r")
#if #user_accts.map { |acct| acct["name"]}.include?(login_name)
if #user_accts.any? {|acct| acct["name"] == login_name }
puts "Sorry, that username has already been taken"
elsif
puts "Choose a password:"
prompt; login_password = gets.chomp
user_accts << create_account(login_name, login_password)
File.open("cust_accts.txt", "a") { |file| file.puts(user_accts)}
end
original if/else statement:
if login_name == #??? #user_accts.has_key?(login_name) ???
puts "Sorry, that username has already been taken"
elsif
puts "Choose a password:"
prompt; login_password = gets.chomp
user_accts << create_account(login_name, login_password)
File.open("cust_accts.txt", "a") { |file| file.puts(user_accts)}
end
This is exactly what is inputted to the cust_accts.txt file using this command:
user_accts << create_account(login_name, login_password)
File.open("cust_accts.txt", "a") { |file| file.puts(user_accts)}
cust_accts.txt
{"name"=>"Tom", "password"=>"popcorn", "balance"=>0}
{"name"=>"Avril", "password"=>"chain", "balance"=>0}
It's not quite clear what your starting point is.
Assuming you have parsed your text file into #user_accts, so you have:
#user_accts = [{"name"=>"Tom", "password"=>"popcorn", "balance"=>0},
{"name"=>"Avril", "password"=>"chain", "balance"=>0}]
Then you would want to do:
if #user_accts.map {|acct| acct["name"]}.include?(login_name)
puts "Sorry, that username has already been taken"
else
# ...
end
#user_accts = [{"name"=>"Tom", "password"=>"popcorn", "balance"=>0},
{"name"=>"Avril", "password"=>"chain", "balance"=>0}]
if #user_accts.any? {|acct| acct["name"] == "Tom" }
puts "Sorry, that username has already been taken"
else
# ...
end
#=> Sorry, that username has already been taken
It seems like your problem is "How do I store objects in ruby for use at a later date?". If you want to use a text file you need to put it into a format that can be parsed back into a ruby object like JSON or XML. I would recommend using a database though. A database like SQLite is very light weight and easy to learn. An advantage to using a DB is that when you use a DB you can set an option to have your results returned as a hash.
I had a similar problem, eventually decided that a DB was the way to go.

Ruby command line program that saves and updates users/preferences

I'm building an application that takes in stdin to save a user and their preferences. Should I write the stdin to a text file and save the user input there?
commandline.rb
class CommandLine
def initialize(filename)
#file = File.open(filename, 'w')
end
def add_user(input)
#file = File.open('new_accounts.txt', 'r+')
#file.write(input)
puts input
end
def run
puts "Welcome to the Command Line Client!"
command = ''
while command != 'quit'
printf "enter command: "
input = gets.chomp
parts = input.split
command = parts[0]
case command
when 'quit' then puts 'Goodbye!'
when '-a' then add_user(parts[1..-1].join(" "))
else
puts 'Invalid command #{command}, please try again.'
end
end
end
end
a = CommandLine.new('new_accounts.txt')
a.run
Let's say I want the user to enter '-a tommy likes apples' in the command line, I want it to output:
tommy likes apples
The same user tommy could also input '-a tommy likes oranges' which would then update his previous preference:
tommy likes oranges
Any help/direction is appreciated, thanks!
I don't see a problem with using a text file if you are doing something simple. Alternatives are many and without more detail I'm afraid I can't make a good recommendation.
def add_user(input)
File.open('new_accounts.txt', 'w') {|file|
file.write(input)
}
puts input
end
FYI: This will make it so that your text file updates. :-)
EDIT: Changed the add_user method.

Resources