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
Related
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.
I'm trying to expand upon Peter Cooper's dungeon game in Beginning Ruby and I want the game to address the player by name at each room and then ask them where they will go to make the game more interactive. I keep getting this error though:
dungeon.rb:82:in <main>': undefined methodname' for nil:NilClass (NoMethodError)
So the main parts I've added to try to make this work are Dungeon initialize (lines 4-13)
def initialize
player_name = ""
until !player_name.empty?
puts "Enter your name!"
player_name = gets.chomp
end
#player = Player.new(player_name)
#player.name = player_name
#rooms = []
end
The line in question that creates the error is this:
my_dungeon.add_room(:largecave, "Large Cave", "#{#player.name}, you find yourself in a large cavernous cave. To the west is a small aperture", {:west => :smallcave})
Full code is here:
Ruby Dungeon Code
What's going on here?
You probably wanted to use
my_dungeon.player.name
instead of
#player.name
in rooms addition method calls(since player has been defined for Dungeon instance).
So just use these lines instead of ones you currently have:
my_dungeon.add_room(:largecave, "Large Cave", "#{my_dungeon.player.name}, you find yourself in a large cavernous cave. To the west is a small aperture", {:west => :smallcave})
my_dungeon.add_room(:smallcave, "Small Cave", "#{my_dungeon.player.name}, you find yourself in a small, claustrophopic cave. To the east is a small aperture", {:east => :largecave}
By the way, you set name in initialize method, so there is no need for #player.name = player_name. And it is simpler to read while player_name.empty? instead of until !player_name.empty?, consider following refactoring:
def initialize
player_name = ""
while player_name.empty?
puts "Enter your name!"
player_name = gets.chomp
end
#player = Player.new(player_name)
#rooms = []
end
I'm picking up ruby language and get stuck at playing with the chatterbot i have developed. Similar issue has been asked here Click here , I did what they suggested to change the rescue in order to see the full message.But it doesn't seem right, I was running basic_client.rb at rubybot directory and fred.bot is also generated at that directory . Please see the error message below: Your help very be very much appreciated.
Snailwalkers-MacBook-Pro:~ snailwalker$ cd rubybot
Snailwalkers-MacBook-Pro:rubybot snailwalker$ ruby basic_client.rb
/Users/snailwalker/rubybot/bot.rb:12:in `rescue in initialize': Can't load bot data because: No such file or directory - bot_data (RuntimeError)
from /Users/snailwalker/rubybot/bot.rb:9:in `initialize'
from basic_client.rb:3:in `new'
from basic_client.rb:3:in `<main>'
basic_client.rb
require_relative 'bot.rb'
bot = Bot.new(:name => 'Fred', :data_file => 'fred.bot')
puts bot.greeting
while input = gets and input.chomp != 'end'
puts '>> ' + bot.response_to(input)
end
puts bot.farewell
bot.rb:
require 'yaml'
require './wordplay'
class Bot
attr_reader :name
def initialize(options)
#name = options[:name] || "Unnamed Bot"
begin
#data = YAML.load(File.read('bot_data'))
rescue => e
raise "Can't load bot data because: #{e}"
end
end
def greeting
random_response :greeting
end
def farewell
random_response :farewell
end
def response_to(input)
prepared_input = preprocess(input).downcase
sentence = best_sentence(prepared_input)
reversed_sentence = WordPlay.switch_pronouns(sentence)
responses = possible_responses(sentence)
responses[rand(responses.length)]
end
private
def possible_responses(sentence)
responses = []
#data[:responses].keys.each do |pattern|
next unless pattern.is_a?(String)
if sentence.match('\b' + pattern.gsub(/\*/, '') + '\b')
if pattern.include?('*')
responses << #data[:responses][pattern].collect do |phrase|
matching_section = sentence.sub(/^.*#{pattern}\s+/, '')
phrase.sub('*', WordPlay.switch_pronouns(matching_section))
end
else
responses << #data[:responses][pattern]
end
end
end
responses << #data[:responses][:default] if responses.empty?
responses.flatten
end
def preprocess(input)
perform_substitutions input
end
def perform_substitutions(input)
#data[:presubs].each {|s| input.gsub!(s[0], s[1])}
input
end
# select best_sentence by looking at longest sentence
def best_sentence(input)
hot_words = #data[:responses].keys.select do |k|
k.class == String && k =~ /^\w+$/
end
WordPlay.best_sentence(input.sentences, hot_words)
end
def random_response(key)
random_index = rand(#data[:responses][key].length)
#data[:responses][key][random_index].gsub(/\[name\]/, #name)
end
end
I'm assuming that you are trying to load the :data_file passed into Bot.new, but right now you are statically loading a bot_data file everytime. You never mentioned about bot_data in the question. So if I'm right it should be like this :
#data = YAML.load(File.read(options[:data_file]))
Instead of :
#data = YAML.load(File.read('bot_data'))
I am doing a task that requires me add some products together and give a 10% discount providing the total is above £60. I have done the following:
class Checkout
def initialize (rules)
#rules = rules
#cart = []
end
def scan (item)
if product == Product.find(item)
#cart << product.clone
#Clone preserves frozen state whereas .dup() doesn't if use would raise a
#NoMethodError
end
end
def total
#cart = #rules.apply #cart
end
def self.find item
[item]
end
co = Checkout.new(Promotional_Rules.new)
co.empty_cart
co.scan(1)
co.scan(2)
co.scan(3)
puts "Total price: #{co.total}"
puts
co.empty_cart
co.scan(1)
co.scan(3)
co.scan(1)
puts "Total price: #{co.total}"
puts
co.empty_cart
co.scan(1)
co.scan(2)
co.scan(1)
co.scan(3)
puts "Total price: #{co.total}"
puts
However when I run this in irb I get undefined variable or method product. Sounds a bit daft but this should work.
You're using one too many equal signs
def scan (item)
# if product == Product.find(item)
if product = Product.find(item) # <--- should be this
#cart << product.clone
#Clone preserves frozen state whereas .dup() doesn't if use would raise a
#NoMethodError
end
end
Of course, then you'll get a different error since find doesn't exist on Product yet... which I think you're trying to define here:
def self.find item # self should be changed to Product
[item]
end
Then you're going to get an error for apply not existing for Promotional_Rules ...
One of the best ways to debug these errors is follow the stack traces. So for the last error I get the following message:
test.rb:53:in `total': undefined method `apply' for #<Promotional_Rules:0x007f94f48bc7a8> (NoMethodError)
from test.rb:72:in `<main>'
That's basically saying that at line 53 you'll find apply hasn't been defined for #rules which is an instance of Promotional_Rules. Looking at the Promotional_Rules class you've clearly defined that method as apply_to_item and not apply. If you keep following and fixing the rabbit trails like this for stack traces you'll be able to debug your program with ease!
I would like to read the deleted statuses on twitter since i can already have the user_id and status_id of the deleted tatus using "on_delete" method.
here is my code:
require 'rubygems'
require 'tweetstream'
TweetStream::Client.new(USER,PASS).follow(3331681,15846407,30592818,21249843,1367531,428333, 196218494,82158673, :delete => Proc.new{ |status_id, user_id| puts "#{status_id}, #{user_id}"}) do |status|
#is it a retweet
rt=!defined?(status.method_missing("retweeted_status",status.id).class).nil?
puts "retweet?:"
puts rt.inspect
if status.in_reply_to_screen_name.nil?
if rt
puts "Retweeted by :#{status.user.screen_name}"
else
puts "Screen name :#{status.user.screen_name}"
end
else
puts "From :#{status.user.screen_name} to #{status.in_reply_to_screen_name}"
end
puts "Text:#{status.text}"
puts "#{status.created_at}"
puts '*' * 7
puts "user id:#{status.user.id}"
puts "to :#{status.in_reply_to_user_id}"
puts '--' * 25
end
No, you can't. This is a constraint of the Twitter API rather than any Ruby library. It used to be possible but has since been fixed, breaking tweet recovery services such as tweleted.com in the process.