I’m trying to create something like an inventory in ruby, so I can compare "params" against every line in that inventory, but I’m new to the language and I don’t know what might be the best way to do it.
Actually my code looks like this:
def parseParams(params)
max_length = "xxxxxxxxxxx".length
min_length = 2 #c1 for example
if (params.length == 0)
puts "[-] No parameters provided"
return false
elsif (params.length > max_length)
puts "[-] The parameters are too long/invalid"
return false
elsif (params.length < min_length)
puts "[-] The parameters are too short/invalid"
return false
else
if (params == "c1" || params == "c2" || params == "c3")
puts "[+] Valid parameters"
return true
end
end
end
What I want to do is simplify the code and just verify whether "params" exists in this inventory, otherwise, return error.
Someone knows how to do it?, thanks in advance.
To summarise the requirements of your question:
If params is equal to any line in inventory.txt then it's valid, otherwise it's invalid
You can do this:
def parseParams(params)
File.read('inventory.txt').split("\n").include?(params)
end
Related
I have a small code for determining the number of hours per year.
What I am looking for is for a Ruby way to allow different user's input options for all possible valid answer stored in an array
to check if the user provided a valid option by calling include? on the array.
When year consist of 52 weeks.
Week consists of 7 days.
Day consists of 24 hours
My problem comes up when trying to pass different answers for the gets method such as follows:
if answer == "yes" || "yup" || "yeah" || "positive";
if answer == ("yes", "yup", "yeah", "positive")
if answer == ["yes" or "yup" or "yeah" or "positive"]
I receive an error which I couldn't solve
answer = gets.chomp
if answer == "yes" or "yup" or "yeah" or "positive"
puts "Good!"
puts desc_text
my_var = gets.chomp.to_i
if my_var == 3736
puts good_text
else
puts wrong_text
puts bad_text
end
elsif answer == [ "no" || "nop" || "nay || ""negative" ]
puts bad_text
else
puts yes_no
end
I'd like to pass different answer options such as yes, yup, yeah, positive instead of just enclose me to a yes and/or no answer
A more idiomatic Ruby way of allowing for these different user options would be to have all possible valid user input stored in an array, then checking if the user provided a valid option by calling include? on the array. This way, you can update the array with more possible options at a later time. Generally arrays like this are stored as constants, though you can also store them as local variables. I find that for a script like this, variables are fine, but if I'm writing a larger program and I need arrays like this (for example, arrays that specify valid options) in a class, then I use constants to make it easy for other contributors to find them. Another option yet would be to have a configuration file (can be a Ruby file, yaml file, JSON file...) that defines valid options, and then you can load this file when executing your program.
Here is an example of what I mean:
VALID_AFFIRMATIVE_ANSWERS = %w(yes yup yea positive)
VALID_NEGATIVE_ANSWERS = %w(no not nay negative)
answer = gets.chomp
if VALID_AFFIRMATIVE_ANSWERS.include?(answer)
puts "Good!"
puts desc_text
my_var = gets.chomp.to_i
if my_var == 3736
puts good_text
else
puts wrong_text
puts bad_text
end
elsif VALID_NEGATIVE_ANSWERS.include?(answer)
puts bad_text
else
puts yes_no
end
I'm not sure what errors you're receiving, but I'm not sure if you're ever defining some of these variables (for example desc_text etc.).
if code is excetly as you write above your issue is in line written below
elsif answer == [ "no" || "nop" || "nay || ""negative" ]
although it won't work , so the solution for you would be like below
def process_positive_response
my_var = gets.chomp.to_i
if my_var == 3736
puts good_text
else
puts wrong_text
puts bad_text
end
end
answer = gets.chomp
case answer
when 'yes','yup','yeah','positive'
puts "Good!"
puts desc_text
process_positive_response
when 'no', 'nop', 'nay', 'negative'
puts bad_text
else
puts yes_no
end
first why write so much conditions when ruby already does that for you with case statement, and second distribute your code in chunks so it will make your code more traceable.
hi I am having a problem with a method i have written. When the method has finished executing it runs its first 2 lines again even though there is no loop. can anyone tell me why?
here is the code
def print(students)
if sort_by?("letter") then students = letter_sort(students) end
if sort_by?("cohort") then students = cohort_sort(students) end
print_header
i = 0
until i = students.length do
student_name = get_student_name(students[i][:name])
puts "#{i+1}. #{student_name} (#{students[i][:cohort]} cohort)"
i = i + 1
end
end
The two if statements at the top are the ones being executed. Here is the sort_by? method I've written as well.
def sort_by?(string)
puts "would you like to sort by #{string}?"
puts "Enter y/n:"
input = gets.chomp.downcase
while input != "n" or input != "y"
if input == "n"
return false
elsif input == "y"
return true
end
end
end
Any help at all would be appreciated.
I'm able to work this statement to a point but I'd like to add another outcome. How to get the statement to return a value from the same row (headed 'first_name') in the CSV if the boolean statement returns true?
def customer_check(user_pin)
x = false
CSV.read('customers.csv', headers: true).any? do |row|
x = true if row['pin'] == user_pin and row['work_here'] == "YES"
yellow = row['first_name']
if x == true then
puts "Welcome back #{yellow}."
sleep(1.5)
else
puts "login failed. Please try again in 3 seconds..."
sleep(3.0)
login_start
end
navigation_menu
end
If you are 100% sure the pins in your csv are unique you could try this
def customer_check(user_pin)
user = CSV.read('customers.csv', headers: true).detect { |row|
row['pin'] == user_pin && row['work_here'] == "YES"
}
if user
puts "Welcome back #{user['first_name']}."
sleep(1.5)
else
puts "login failed. Please try again in 3 seconds..."
sleep(3.0)
login_start
end
navigation_menu
end
Variable user will be initialized as the corresponding row of the .csv for which the conditional is true. Otherwise it's value will be nil:
detect method according to documentation:
Passes each entry in enum to block. Returns the first for which block is not false. If no object matches, calls ifnone and returns its result when it is specified, or returns nil otherwise.
If no block is given, an enumerator is returned instead.
Bear in mind that you might have to ensure that row['pin'] matches your user_id data type as it may come in as a String in which case you'd have to row['pin'].to_i == user_pin
How to get the statement to return a value from the same row (headed 'first_name') in the CSV if the boolean statement returns true?
Running your code as is, Ruby expects a final "end" and raises this error:
syntax error, unexpected end-of-input, expecting keyword_end
Adding another ending 'end' to your code will result in the if x == true block getting evaluated, but, note the indentation in the following code is arguably clearer. Using this example .csv file, this code will both print Welcome back... and return the first name if x == true:
require 'csv'
def customer_check(user_pin)
x = false
CSV.read('customers.csv', headers: true).any? do |row|
x = true if row['customerNo'] == user_pin && row['lastName'] == "Dunbar"
yellow = row['firstName']
# The if/else clauses are indented within the CSV.read
if x # <-- "== true" is redundant
# puts "Welcome back #{yellow}." # you can lose "yellow" if you want to
puts "Welcome back #{row['firstName']}."
sleep(1.5)
# return yellow # <-- RETURN VALUE
return row['firstName'] # <-- RETURN VALUE
else
puts "login failed. Please try again in 3 seconds..."
sleep(3.0)
# login_start
end
# navigation_menu
end
end
return_name = customer_check('1') # <-- prints "Welcome back John"
puts return_name # <-- "John" is the RETURN VALUE
I'm not sure how you are using login_start or navigation_menu but i hope this helps to answer your question. If it helps, here's the CSV doc
Hi I'm trying to make a blackjack game using Ruby and am trying to make the values of the picture cards all = 10. Is it okay to use the code I use below to accomplish this? (this is all happening in my Card class)
def value
if #number == ("jack" || "queen" || "king")
10
else
#number.to_i
end
end
You can, but not the way you are using it. You either need to use the entire boolean expression in each portion:
if #number == "jack" || #number == "queen" || #number == "king"
or you can make it simpler by checking the contents of an array:
if ["jack", "queen", "king"].include?(#number)
The parens group things that should be evaluated before other things. So, the above says, evaluate:
("jack" || "queen" || "king")
and return the results. Lets try that in irb:
irb(main):004:0> ("jack" || "queen" || "king")
=> "jack"
Since "jack" is truthy there's no need to look at the rest of the list and "jack" is returned.
This will work fine as long as #number is equal to "jack" but not so much for the other values. You want to compare #number against each value until you get a match or exhaust the list. See #PinneyM's answer of
(#number == "jack") || (#number == "queen") ...
That is a valid ruby snippet, but it doesn't do what you think it does: it first evaluates
("jack" || "queen" || "king")
which evaluates to "jack" as that is the first non false/nil value. It then compares #card to this, so your code is equivalent to
def value
if #number == 'jack'
10
else
#number.to_i
end
end
You could compare each in turn (#number == 'jack') || (#number == 'queen') ||..., you could use %w(jack queen king).include?(#number) or you could use a case statement:
def value
case #number
when 'jack', 'queen', 'king'
10
else
#number.to_i
end
end
I'm currently ripping my hairs off to find a solution. I need to parse some Json but the json gem don't allow me to parse more than 2 levels deep, so I have to do a lot of each block. And to eliminate some datas that I don't want I need to do an if/else.
So here is what I'd like to do:
result['person']['participation'].each do |participation|
if participation['movie']['release'] { |release| release['releaseState']['code'] == 3011 || release['releaseState']['code'] == nil }
next
else
puts title = participation['movie']['originalTitle']
end
end
I tried with 'unless' too, but I fear that I can't pass block in statement. If not, do you have a way to do what I need ?
Many thanks !
Here is the JSON http://api.allocine.fr/rest/v3/filmography?partner=YW5kcm9pZC12M3M&profile=medium&code=5568&filter=movie&format=json
I need to see your document structure... but if participation['movie']['release'] is an Array, you can use Array#any?
result['person']['participation'].each do |participation|
if participation['movie']['release'].any? { |release| release['releaseState']['code'] == 3011 || release['releaseState']['code'] == nil }
next
else
puts title = participation['movie']['originalTitle']
end
end
If it's not an Array, please post a document example.