Ruby loop create empty lines - ruby

I'm newbie in Ruby (frankly, I've just started learning it for fun, without any future plans), and I've noticed strange behaviour of loops. I assume my problem comes from lacks in knowledge in the mechanics of Ruby.
boysNames = ["Martin", "Lucas", "John"]
#class only for one method. I know it's not absolutely correct, but huh I'm just learning Ruby
class Human
def initialize(name)
#name = name;
end
String name = ""
def getName()
puts #name;
end
end
Array boys = []
#create objects
for x in boysNames
tempBoy = Human.new(x)
boys.push(tempBoy)
end
#output for class
puts "Method 1: for in loop \n"
for x in boys
puts x.getName()
end
puts "\nMethod 2: manual array[var] \n"
boys[0].getName()
boys[1].getName()
boys[2].getName()
puts "\nMethod 3: .each do \n"
boys.each do |i|
puts i.getName()
end
#output for Array
puts "Method 1: for in loop \n"
for x in boysNames
puts x
end
puts "\nMethod 2: manual array[var] \n"
puts boysNames[0]
puts boysNames[1]
puts boysNames[2]
puts "\nMethod 3: .each do \n"
boysNames.each do |i|
puts i
end
#loop through the boys array
puts "\nboys array: \n"
for x in boys
puts x
end
So my question is: Why when I loop through the array everything is fine, and when I loop through the class, my results are divided by newlines? Are there any "invisible" objects that I couldn't find? As you can see my last loop found only three objects with different places in the memory.
I will be pleased, if the answer contains explanation of "how it works".
Thank you in advance ;)
P.S. Output:
Method 1: for in loop
Martin
Lucas
John
Method 2: manual array[var]
Martin
Lucas
John
Method 3: .each do
Martin
Lucas
John
Method 1: for in loop
Martin
Lucas
John
Method 2: manual array[var]
Martin
Lucas
John
Method 3: .each do
Martin
Lucas
John
boys array:
#<Human:0x007f2a586db788>
#<Human:0x007f2a586db648>
#<Human:0x007f2a586db5d0>
P.S.S. I'm using this as the Ruby interpreter/compiler (I heard that Ruby can also be compiled, so...)

You're calling puts x.getName(), but getName() already has puts inside of it.
puts adds a newline to the end of each argument if there is not one already.
print does not add a new line.
(What is the difference between print and puts?)

Related

List in Ruby gem cli

I am making a ruby cli that outputs a list of game deals scraped from a site.
The list prints out promptly using
def games_sales
Deal.all.each_with_index do |deal, index|
puts "#{index + 1}. #{deal.title}"
end
puts "What game do you want to see?"
input = gets.strip
game_selection(input.to_i)
end
My problem comes when asking the user to select an item from the list.
def game_selection(input)
deal = Deal.find_by_index(input)
#binding.pry
deal.each do |deal|
puts "#{deal.index}"
puts " Name: #{deal.title}"
puts " Price: #{deal.price}"
puts " Store: #{deal.store}"
puts " Expiration: #{deal.expiration}"
end
deal
end
It returns the int input but only the first item on the list every time.
I forgot my find_by_index method:
def self.find_by_index(input)
all.select do |deal|
end
end
which is incomplete
Not 100% sure if I got your question right and if you're using Rails, but Deals.all let me think of this.
I had to replace Deals.all with DEALS for testing as I haven't got a rails app running. So I used an Array of OpenStructs to fake your Model result.
# this fakes Deals.all
require 'ostruct'
DEALS = [
# add any more properties the same way as title, separated by comma
OpenStruct.new(title: 123),
OpenStruct.new(title: 456)
]
def games_sales
DEALS.each_with_index do |deal, index|
puts "#{index + 1}. #{deal.title}"
end
puts "What game do you want to see?"
input = gets.strip
game_selection(input.to_i)
end
def game_selection(input)
deal = DEALS.at(input-1)
p deal[:title]
end
def self.find_by_index(input)
all.select do |deal|
deal.index == input
end
end
games_sales
Result when choosing 1 is 123, choosing 2 you'll get 456, due to p deal[:title] above in the code.
I think your find_by_index need to get the right index and in my example I had to use at(index) as at(input-1) in order to get the right result.
I really hope this helps somehow and I suggest that you add the expected result to your question, in case my answer does not help you.

Confused about using reduce and what it's actually trying to do

I have done Rails development a bit but haven't for a while.
I have never used reduce / inject other than to sum up values (which seems to be the main example I've seen online) but would like to understand better what it does (and to be honest, just its syntax). I have heard it referred to as the functional part of Ruby but based upon examples, not sure what that means.
Looking at the example in the docs (the longest word example) https://ruby-doc.org/core-2.4.0/Enumerable.html#method-i-reduce seems to imply that it is useful for selecting a value out of a series at end but this doesn't seem very functional.
My understanding is that it accumulates to the initial value passed into reduce. But in this code fragment, I'm not sure why it's not accumulating (I'm expecting "some joe birds joe bees" or some variation).
# expect 'some joe birds joe bees'
def say_joe(name)
puts "within say_joe #{name}"
" joe #{name}"
end
a = %w(birds bees)
starting = "some"
b = a.reduce(starting) do |total, x|
puts x
say_joe(x)
end
puts "-----"
puts "starting: #{starting}"
puts "a: #{a}"
puts "b: #{b}"
with output:
birds
within say_joe birds
bees
within say_joe bees
-----
starting: some
a: ["birds", "bees"]
b: joe bees
What is the magic of reduce?
The accumulation (in this case a string concatenation) doesn’t happen automatically. You still need to return the new accumulator value (remember in Ruby the last statement is also implicitly the return value).
This does what you’d expect:
def say_joe(name)
puts "within say_joe #{name}"
" joe #{name}"
end
a = %w(birds bees)
starting = "some"
b = a.reduce(starting) do |total, x|
puts x
total << say_joe(x)
end
puts "-----"
puts "starting: #{starting}"
puts "a: #{a}"
puts "b: #{b}” # some joe birds joe bees

Adding inside function

I have some code that won't add two numbers. What have I done wrong?
class Add
##starting_value = 5
def self.Adding
puts "How much do you want to add? "
user_choice = gets.to_i
user_choice + ##starting_value
puts "new value is"
puts ##starting_value
end
end
The problem is this line:
user_choice + ##starting_value
That adds the two values and then throws out the answer. You need to store the answer in a variable:
##starting_value = user_choice + ##starting_value
Ruby has a special shortcut for this
##starting_value += user_choice
I highly recommend reading the Pickaxe book. I assume you already have a Ruby implementation installed on your computer.
Create a file called, say, add.rb. I would try to keep things as simple as possible:
class Add
#amount = 5
def self.add
puts "How much do you want to add?"
puts "New value is #{#amount + gets.to_i}"
end
end
Add.add # add is a class method
Then run it with ruby app.rb. The output should be something like:
How much do you want to add?
100
New value is 105

calling an array defined in one method in another method

am learning ruby and i had come across this particular issue.
I have method which reads the user input data into an array and i have another method which displays the values in the same array to the user with some processing.
However this doesnt seem to be the correct way as the system always throws a
Arraypass.rb:23:in <main>': undefined local variable or methodnames' for main:Object (NameError)
Appreciate if someone can show a way forward in this,
for example:
class School
def askdetails
print "How many students are there"
n=(gets.chomp.to_i - 1)
print "Enter names one by one"
names=Array.new(n)
for i in (0..n)
names[i]=gets.chomp
end
return names,n
end
def showdetails(names,n)
for i in (0..n)
puts names[i]
end
end
end
stud=School.new
stud.askdetails
stud.showdetails(names,n)
Write the code as
#!/usr/bin/env ruby
class School
def askdetails
print "How many students are there"
n = gets.chomp.to_i - 1
print "Enter names one by one"
names = Array.new(n)
for i in (0..n)
names[i]=gets.chomp
end
return names,n
end
def showdetails(names,n)
for i in (0..n)
puts names[i]
end
end
end
stud = School.new
names, n = stud.askdetails
stud.showdetails(names,n)
The thing, you missed is #askdetails methods returning an Array, which you didn't assign any where before using those.
Read Array Decomposition, this is what I did here :
names, n = stud.askdetails
here is your answer:
names,n = stud.askdetails
stud.showdetails(names,n)

Question about "gets" in ruby [duplicate]

This question already has answers here:
Ruby: String Comparison Issues
(5 answers)
Closed 3 years ago.
I was wondering why when I'm trying to gets to different inputs that it ignores the second input that I had.
#!/usr/bin/env ruby
#-----Class Definitions----
class Animal
attr_accessor :type, :weight
end
class Dog < Animal
attr_accessor :name
def speak
puts "Woof!"
end
end
#-------------------------------
puts
puts "Hello World!"
puts
new_dog = Dog.new
print "What is the dog's new name? "
name = gets
puts
print "Would you like #{name} to speak? (y or n) "
speak_or_no = gets
while speak_or_no == 'y'
puts
puts new_dog.speak
puts
puts "Would you like #{name} to speak again? (y or n) "
speak_or_no = gets
end
puts
puts "OK..."
gets
As you can see it completely ignored my while statement.
This is a sample output.
Hello World!
What is the dog's new name? bob
Would you like bob
to speak? (y or n) y
OK...
The problem is you are getting a newline character on your input from the user. while they are entering "y" you are actually getting "y\n". You need to chomp the newline off using the "chomp" method on string to get it to work as you intend. something like:
speak_or_no = gets
speak_or_no.chomp!
while speak_or_no == "y"
#.....
end
once you use gets()...
print that string.. using p(str)
usually string will have \n at the end.. chomp! method should be used to remove it...

Resources