No Method Errors in Ruby - ruby

I was able to get a menu and pull up names of cat breeds, however when I continue to learn about the cat's breed I get this error down below. Not sure where to go from here. Am I suppose to delete something off? or perhaps try another api? really running out of ideas here.
Error below:
Traceback (most recent call last):
4: from bin/run.rb:5:in `<main>'
3: from /Users/jason/Development/code/Cat Breeds/Cat_breeds/lib/cli.rb:9:in `call'
2: from /Users/jason/Development/code/Cat Breeds/Cat_breeds/lib/cli.rb:24:in `menu'
1: from /Users/jason/Development/code/Cat Breeds/Cat_breeds/lib/cli.rb:44:in `list_of_breeds' /Users/jason/Development/code/Cat Breeds/Cat_breeds/lib/cli.rb:54:in `breed_selection': undefined method `get_metric_weight' for
#<CatBreed:0x00007fc581afc488> (NoMethodError)
in my cli.rb file
class CLI
def initialize
API.new.get_breed_data
end
def call
greeting
menu
end
def greeting
puts "Welcome! Start searching for Cat breeds"
puts ""
puts "--To search for cat breeds, enter 'breeds'"
puts ""
puts "--If there is nothing you would like to do at the moment, enter 'exit'"
end
def menu
input = gets.strip.downcase
if input == "breeds"
list_of_breeds
elsif input == "exit"
goodbye
else
invalid_entry
end
end
def goodbye
puts "Goodbye!"
end
def list_of_breeds
puts "Select which breed you would like to know about:"
CatBreed.all.each_with_index do |breed, index|
puts "#{index + 1}. #{breed.name}"
end
input = gets.strip.downcase
breed_selection(input)
end
def breed_selection(breed)
input = gets.strip.downcase
breed = CatBreed.find_by_name(breed)
if breed
puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
puts "Name of Breed: #{breed.name}"
puts "Approximate Weight: #{breed.get_metric_weight}"
puts "Approximate Height: #{breed.get_metric_height}"
puts "Bred For: #{breed.bred_for}"
puts "Breed Group: #{breed.breed_group}"
puts "Average Life Span: #{breed.life_span}"
puts "Temperament: #{breed.temperament}"
puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
puts ""
puts "To continue searching for breeds, enter 'breeds'."
puts "If there is nothing else you would like to do, enter 'exit'."
puts ""
puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
menu
else
incorrect_breed_name
end
end
def incorrect_breed_name
puts "The breed name that you entered may have been spelled incorrectly."
puts "Please enter 'breeds' to pull up the list and try again."
menu
end
def invalid_entry
puts ""
puts "Hmmmmmm, I'm not understanding, please try again."
puts ""
menu
end
#binding.pry
end
something I'm doing wrong here? If you need more info let me know..

The error message says:
/Users/jason/Development/code/Cat Breeds/Cat_breeds/lib/cli.rb:54:in `breed_selection':
undefined method `get_metric_weight' for #<CatBreed:0x00007fc581afc488> (NoMethodError)
This error has got nothing to do with VSCode. It says that your CatBreed instance does not respond to a get_metric_weight method.
However, you have not shown the CatBreed class definition above, so I cannot comment further on the resolution.
Your code also assumes it has methods such as get_metric_height, bred_for and breed_group. If these methods aren't defined either, then I would expect a similar error to be raised once this issue is fixed.

Related

rspec fails even when variables should match

Methods in my class:
def get_class_info
#class_name = get_class_name
end
def get_class_name
puts "Enter the name for your class. Enter 'done' to return to the main prompt."
input = gets.chomp
if input.valid_class_name?
class_name = input.titleize
elsif input.downcase == "done"
run
else
puts "Invalid class name."
get_class_name
end
class_name
end
My test:
it "stores the name in the #class_name property" do
expect(cli.class_name).to eq('Song')
allow(cli).to receive(:gets) {'song'}
cli.get_class_info
end
It fails, saying it expected "Song" but got nil.
If I comment out the expect line and add a pry to the end of the test, querying cli.class_name returns "Song"!!!
Why is this test failing??
Update: Okay, moving the expect line to the bottom of the test apparently solved it. But I'm confused because usually the expectation goes before the actual method call. Am I wrong? What am I missing here?

Ruby hash.new error undefined local variable or method ... for main:Object

I'm trying to create a new hash (group) to which I'll pass values for name, groceries, fuel_and_accommodations and recreational_activities. Actually, eventually I'll need a hash nested within the group hash (for each traveler). My issue right now is that I get this message:
undefined local variable or method `group' for main:Object
(repl):5:in `user_name'
(repl):18:in `block in enter_expenses'
(repl):15:in `times'
(repl):15:in `enter_expenses'
(repl):34:in `'
I'm just learning Ruby. Any help would be greatly appreciated!
group = Hash.new
def user_name
puts "What is the name of this traveler?"
group["name"]= gets.chomp.capitalize
end
def enter_expenses
puts "Welcome to the Expense Tracker System!\n".upcase
puts "__________________________________________"
puts "\nUse this system to track your group's expenses when traveling."
print "Ready to get started? Enter yes to continue"
ready_to_expense = gets.chomp.downcase
4.times do
if ready_to_expense == "yes"
puts "Welcome #{user_name}! Enter your expenses below:\n"
puts "Amount spent on groceries:"
group["groceries"]= gets.chomp.to_f
puts "Amount spent on fuel & accommodations:"
group["fuel_and_accommodations"]= gets.chomp.to_f
puts "Amount spent recreational activities:"
group["recreational_activities"] = gets.chomp.to_f
elsif "Please come back when ready to enter your expenses."
end
end
end
enter_expenses
create_travelers
puts "__________________________________________"
puts "Thanks for using the expense tracker system!".upcase
Local variables in Ruby does not get into methods; methods declare their own scope, they don’t act like closures. You might use instance variable instead:
#group = Hash.new # NOTE #
...
def enter_expenses
...
4.times do
if ready_to_expense == "yes"
#group["groceries"]= gets.chomp.to_f # NOTE #
...
end
end
end

Ruby: creating a case statement that checks csv file for string to authenticate user (terminal only)

I apologies if this is simple but I'm just starting out. Any constructive help welcome.
Problem:
Trying to create authentication from ruby terminal to CSV.
I'd like to create clean (and as short as possible) loop statement that goes to csv file checks the top row for header "pin" and then checks the gets.chomp entry against that to authenticate.
require 'csv'
class Menu
def self.login
system "clear"
puts "Welcome to Hip-Bikes & Coffee"
puts "Please login with your pin:"
print "> "
customer_pin = gets.chomp
verified = authentication(customer_pin)
end
def self.authentication(customer_pin)
case
when CSV.foreach('customers.csv', headers: true) { |row| ["pin"] == login.verified }
puts verified
else
puts "login failed. Please try again in 3 seconds..."
sleep(3.0)
self.login
This should work for you
UPD
require 'csv'
class Menu
class << self
def login
login_start
verified(gets.chomp)
end
def verified(input)
if authentication(input)
puts 'verified'
else
failed
end
end
def authentication(customer_pin)
CSV.foreach('customers.csv', headers: true).any? { |row| row['pin'] == customer_pin }
end
def failed
puts "login failed. Please try again in 3 seconds..."
sleep(3.0)
login
end
def login_start
system "clear"
print "Welcome to Hip-Bikes & Coffee\nPlease login with your pin:\n> "
end
end
end

Building proper class and passing a class method

class Health
def initialize()
#hydration=hydration
end
def hydration
puts"Amount of Water drunk(in oz):"
x=gets.chomp
if #{x}>=20
puts"Good job! keep on it"
elsif #{x} >=(10...20)
puts"Could do better"
else
puts"Not healthy. Go get hydration"
end
end
drinks=Health.new()
puts drinks.hydration
end
I am new to ruby and what i'm trying to achieve is to be prompted. i'm getting the "syntax error, unexpected end-of-input, expecting keyword_end" on the puts drinks.hydration
I dont think you should get any syntax error with your current code. In order to make it working you need to remove the comments in if statements. Also the initialize statement is redundant as you are making explicit call to the method hydration in puts drinks.hydration.
class Health
def hydration
puts "Amount of Water drunk(in oz):"
x=gets.chomp.to_i
if x>=20
puts "Good job! keep on it"
elsif (10...20).include? x
puts "Could do better"
else
puts "Not healthy. Go get hydration"
end
end
end
drinks=Health.new()
puts drinks.hydration

as_null_object not passing with two inputs

I'm working through the RSpec Book, and I have the following test code:
require 'spec_helper'
module Codebreaker
describe Game do
describe "#start" do
let(:output) { double('output').as_null_object }
let(:game) { Game.new(output) }
it "sends a welcome message" do
output.should_receive(:puts).with('Welcome to Codebreaker!')
game.start
end
it "prompts for the first guess" do
output.should_receive(:puts).with('Enter guess:')
game.start
end
end
end
end
which corresponds to the following code:
module Codebreaker
class Game
def initialize(output)
#output = output
end
def start
#output.puts 'Welcome to Codebreaker!'
#output.puts 'Enter a guess:'
end
end
end
Since I've set :output up as a double.as_null_object, I expect it to ignore any arguments/methods it is not expecting. For the first test (sends a welcome message), that's what it does, and it passes. The second test, however, is giving me this error:
Failure/Error: output.should_receive(:puts).with('Enter guess:')
Double "output" received :puts with unexpected arguments
expected: ("Enter guess:")
got: ("Welcome to Codebreaker!"), ("Enter a guess:")
# ./spec/codebreaker/game_spec.rb:16:in `block (3 levels) in <module:Codebreaker>'
Why is the double returning both "Welcome to Codebreaker!" and "Enter a guess" when I have explicitly told it to only expect "Enter a guess:", and how can I fix this while maintaining this same setup/structure?
The second case is failing because you have a typo in your expectation. You meant Enter a guess: instead of Enter guess:.
Unfortunately, rspec is very picky about wording on strings. In your start method you wrote "Enter guess" instead of "Enter a guess:".
It's important to follow the wording to a T, when you start having to raise an error, rspec gives you a very nasty response.
Good luck! Rspec is a great tool as you get further into it.

Resources