Undefined method for nil:Nilclass
In a class, a method counts the number of words in a paragraph.An error occurs when a method is called(1). I can’t understand how to pass the argument methods using send.
If I remove the class and put the def calc_1(paragraph) method into the loop, then everything works, I start calling the select method. It turns out he does not see my books variable with text, when there is a class.
#books = "You can use this knowledge to create small tools that might help."
class Filecalculation
def select
loop do
puts "# Will we search : сounting words in text File(1)".cyan
print "\n>>>>>> "
input = gets.chomp
search_method = "calc_#{input}".to_sym
if (respond_to?(search_method))
contents = send(search_method, #books)
end
end
end
def calc_1 paragraph
word_count = paragraph.split.length
puts "#{word_count} words"
end
end
Filecalculation.new.select
If replaced by search_method = "calc_#{input}".to_sym also works.
Helped add def initialize #books end.
Instead of contents = send (search_method, #books) you can use send (search_method, #books).
require "colorize"
class Filecalculation
def initialize
#books = "You can use this knowledge to create small tools that might help you."
end
def calc_1 paragraph
word_count = paragraph.strip.squeeze(' ').count(' ') + 1
puts "#{word_count} words"
end
def select
loop do
puts "# Will we search : Calculation_lines paragraph(1)".cyan
print "\n>>>>>> ".yellow
input = gets.chomp
search_method = "calc_#{input}" #.to_sym
if (respond_to?(search_method))
contents = send(search_method, #books)
else
puts "exit "
exit
end
end
end
end
Filecalculation.new.select
Related
I am attempting to use the String from a variable to call a Method within the program.
How can one use the String from the Variable to call said Method without having to nest or make multiple checks?
module Player
##location = "location"
def Player.input(input)
if input == "look"
"Call Method from ##location"
end
end
def Player.set_location(input)
##location = input
end
end
def input
print "> "
Player.input(#stdin.gets.chomp)
end
def "name of Method can be same as ##location"
...
end
def "another name of Method can be same as ##location"
...
end
def "another name, etc"
...
end
What do you mean by without having to nest ? I wonder if your code is a contrived example. Defining methods in the special object main is OK for a quick test, if they are also called from main, otherwise they must be put in a class.
So the answer could be as simple as that :
module Player
#location = 'location'
def Player.input(input)
puts "in Player.input(#{input})"
if input == 'look'
puts "Calling method <#{#location}>"
Switch.send(#location)
else
puts 'wrong input, must be "look"'
end
end
def Player.set_location(input)
#location = input
end
end
def input
print "> "
Player.input(gets.chomp)
end
class Switch
def self.abc
puts 'in abc'
end
def self.def
puts 'in def'
end
def self.location
puts 'in location'
end
def self.method_missing(name, *args, &block)
puts "There is no method #{name} in #{self.name}"
end
end
input
input
Player.set_location('abc')
input
Player.set_location('xyz')
input
Execution :
$ ruby -w t.rb
> looc
in Player.input(looc)
wrong input, must be "look"
> look
in Player.input(look)
Calling method <location>
in location
> look
in Player.input(look)
Calling method <abc>
in abc
> look
in Player.input(look)
Calling method <xyz>
There is no method xyz in Switch
How do I write a rspec test for the following.
the value that gets passed in is this...
90A14F 1.4
def classname
def init
#input_colors = Array.new
end
def speak
puts "enter your line of color values"
result = STDIN.gets.chomp
new_result = result.gsub!(/([\s])+/,':')
#input_colors << new_result
end
end
How do I write an rspec 3.1 test for this speak method that test if gets.chomp is...90A14F 1.4
They will get an instance var #input_colors == ["90A14F:1.4"]
There are some issues in your example. I would change and fix it to something like this:
class ColorReader # with `class` and an upcase class name
def initialize # not `init`
#colors = [] # the use of `Array.new` is uncommon
end
def read
puts "enter your line of color values"
result = STDIN.gets.chomp
new_result = result.gsub!(/([\s])+/,':')
#colors << new_result
end
end
Then a test could look like this:
describe ColorReader do
describe '#read' do
let(:input) { "90A14F 1.4\n" }
subject(:color_reader) { ColorReader.new }
before do
allow(color_reader).to receive(:puts).and_return(nil)
allow(STDIN).to receive(:gets).and_return(input)
end
it 'writes to the console' do
color_reader.read
expect(color_reader).to have_received(:puts).
with("enter your line of color values").once
end
it 'reads from STDIN' do
color_reader.read
expect(STDIN).to have_received(:gets).once
end
it 'returns the sanitized input' do
expect(color_reader.read).to eq(['90A14F:1.4'])
end
end
end
Btw. I would prefer to explicitly test the new value of the #colors array (perhaps with attr_reader :colors) and not the implizit return value of the read method. If you have a reader for the #colors then the last spec can be changed to:
it 'adds the sanitized input to `colors`' do
expect {
color_reader.read
}.to change { color_reader.colors }.from([]).to(['90A14F:1.4'])
end
I've read my code up and down for about 30 mins now. I can't for the life of me see where user_response is undefined. I'm very new to coding so I don't know how much of the code would be appropriate to paste in here. I figure that launch and get_action are essential but the rest couldn't hurt?
error => rb:32:in `launch!': undefined local variable or method `user_response' for
<Guide:0x007fb019984718> (NameError)
class Guide
class Config
##actions = ['list', 'find', 'add', 'quit']
def self.actions
##actions
end
end
def initialize(path=nil)
# locate the restaurant text file at path
Restaurant.filepath = path
if Restaurant.file_usable?
puts "Found restaurant file."
# or IF a new text file can't be created, create a new file
elsif Restaurant.create_file
puts "Created restaurant file."
# exit if create fails
else
puts "Exiting"
exit!
end
end
def launch! #! means that it is a strong powerful method!
introduction
# action loop
result = nil
until result == :quit
action = get_action
result = do_action(user_response)
end
conclusion
end
def get_action
action = nil
# Keep asking for user input until we get a valid action
until Guide::Config.actions.include?(action)
puts "Actions: " + Guide::Config.actions.join(", ") if action
print "> "
user_response = gets.chomp
action = user_response.downcase.strip
end
return action
end
def do_action(action)
case action
when 'list'
puts "Listing..."
when 'find'
puts "Finding..."
when 'add'
puts "Adding..."
when 'quit'
return :quit
else puts " I don't understand that command."
end
end
def introduction
puts "<<< Welcome to the Food Finder >>>"
puts "This is an interactive guide to help you find the food you crave."
end
def conclusion
puts "<<< Goodbye and Bon Appetit! >>>>"
end
end
I think you want to do this :
def launch! #! means that it is a strong powerful method!
introduction
# action loop
result = nil
until result == :quit
result = do_action(get_action)
end
conclusion
end
The only time you define a variable called user_response is in your get_action method.
The way you define it there makes it a local variable and it will not be accessible from anywhere but inside the get_action method.
I'm trying to build a relatively simple app in ruby. However I am unable to get my object to return anything other than 0 when puts obj.to_s is called on it. I understand the quality of the code may be poor (and wouldn't mind any hints).
Help please!
class Docpart
def Docpart.new(inputAsString,typeAsInteger)
#value = inputAsString
#type = typeAsInteger.to_i # 0 = title, 1 = text, 2 = equation (can't be done yet), 3 = table
end
def Docpart.to_s
return "Type is #{#type}, value is #{#value}"
end
end
module Tests
def Tests.test1()
filetree = Array.new(0)
filetree.push( Docpart.new("Title",0))
filetree.each{|obj| puts obj.to_s}
return filetree[0]
end
end
puts Tests.test1.to_s
gets.chomp
Because you defined class method to_s not instance one. Also writing constructor in Ruby is a little different. You need to write this that way:
class Docpart
def initialize(inputAsString,typeAsInteger)
#value = inputAsString
#type = typeAsInteger.to_i # 0 = title, 1 = text, 2 = equation (can't be done yet), 3 = table
end
def to_s
"Type is #{#type}, value is #{#value}"
end
end
module Tests
def self.test1
filetree = []
filetree << Docpart.new("Title",0)
filetree.each{ |obj| puts obj.to_s }
filetree[0]
end
end
puts Tests.test1.to_s
gets.chomp
PS Read any book about Ruby and any styleguide like Githubbers or bbatsov one.
class DobbsyKretts
def initialize
#Receive idea
puts "Enter an idea, a secret or anything else you want to secretize; hit enter to stop typing and save the file"
(#idea = gets).reverse.upcase
#Filename and saving - to encrypt the file
puts "Enter the file name you'd like to have this saved as; Type PLAN at the beginning for plans and REM for reminders"
(#file_name = gets.chomp.upcase)
File::open("DobbsyKrett-"+ #file_name + ".txt", "w") do |f|
f << #idea
end
end
def unzip
puts "Do you want to withdraw PLAN or REM"
response = gets.chomp.upcase!
puts "Invalid" if !["PLAN","REM"].include?(response)
file_contents = nil
Dir['DobbsyKrett-'+response+"*.txt"].each do |file_nom|
file_contents = File.read(file_nom)
end
puts file_contents
end
end
somethingsomething1 = DobbsyKretts.new
somethingsomething1.unzip
def unzip
puts "Do you want to withdraw PLAN or REM"
#response = gets.strip
if #response.downcase != "plan" and #response.downcase != "rem"
puts "Invalid" end
Dir["DobbsyKrett-"+#response+".txt"].each do |file_nom|
#value = file.read(file_nom)
end
puts #value
end
end
The function gets will return a string with the line-ending character at the end which is not what you expected. To remove it, use the chomp function:
#response = gets.chomp
It is okay for a method (e.g. unzip) to create new instance variables (e.g. #valueholder). In general it's always better for your variables to have the smallest possible scope, so unless you need to read valueholder later, you should just use a local variable (remove the # from the name):
Dir["DobbsyKrett-"+#response+".txt"].each do |file_nom|
valueholder = File.read(file_nom)
end
puts valueholder
Also, valueholder is a terrible name for a variable but if you made it a local variable that could be excused.
Also, your block startings/endings are mismatched. Here's a fixed version of your function that shouldn't result in syntax errors:
def unzip
puts "Do you want to withdraw PLAN or REM"
response = gets.chomp.downcase
if !["plan","rem"].include? response
puts "Invalid"
else
Dir["DobbsyKrett-#{response}.txt"].each do |file_nom|
valueholder = file.read(file_nom)
end
puts valueholder
end
end
Edit: You should capitalize File to correctly call File.read.