Why won't this command work in this specific code? - ruby

How would i go about this?
I tried
Net::HTTP.new(#site).head('/').kind_of? Net::HTTPOK
but I receive this:
error: in `kind_of?': class or module required (TypeError)
I think there is something wrong with my code, can you please take a look at it? I know its very messy and pretty bad, i'm a first year programming student and i'm learning. If you have any ideas for improvement, let me know!
Also, there is something messed up with the ends contained within. For some reason i get an unexpected end error when i try to end all the defs.
Here is my code in context:
def begindownload
require 'net/http'
puts "Enter the URL of the site that you want to rip images from (use www.*website*.com/folder/file.html or other extension format):"
while #site = gets.chomp
puts "Querying " + #site
if Net::HTTP.new(#site).head('/').kind_of? Net::HTTPOK == true
puts "Site is online!"
else
puts "Site is offline. Try again."
end
end
end

In your code you are using the line:
if Net::HTTP.new(#site).head('/').kind_of? Net::HTTPOK == true
The == is being evaluated first causing Net::HTTPOK == true to be evaluated to false. The rest of the statement then becomes:
if Net::HTTP.new(#site).head('/').kind_of? false
Causing your TypeError.
You don't need to check == true when you are doing an if statement. If the statement after the if evaluates to true then the if will be evaluated. Checking if a boolean == true is considered bad form anyway.

Have you tried .instance_of instead?

Related

Ruby script ignores conditional and breaks method without throwing errors

I have this (I believe) straight and easy method meant to verify if a certain string only includes numbers and isn't empty.
class String
def is_number?
puts "Here it's working, 1"
if self.scan(/\D/).empty? and self != ""
return true
puts "true"
else
return false
puts "false"
end
puts "Here it's working, 2"
end
end
"asd".is_number?
puts "Here it's working, 3"
The result is quite astonishing to me:
The method works until before the conditional. At that point it doesn't go with the "then" nor the "else" options (which, up to today, I never thought to be an option too), and instead breaks the method. Then, it proceeds to the following command. Finally, at the end of the program it sits there without throwing any error.
I honestly don't know how to proceed at this point.
When you used return in a method it will not execute any code after that, if you are expecting true/false to print you should put it above the return statement
def is_number?
puts "Here it's working, 1"
if self.scan(/\D/).empty? and self != ""
puts "true"
return true
else
puts "false"
return false
end
puts "Here it's working, 2"
end
Note:- "Here it's working, 2" statement will never execute as there will be return statement before that.
it doesn't go with the "then" nor the "else" options
No, this is not what happens here, as described in the answer from Salil.
For the future, if you formulate a hypothesis about your code, you should prove or disprove it. Not for us, for yourself. Else how do you know this is actually what is happening?
For example, something like this would reliably verify that the control does indeed enter one of the conditional branches.
if self.scan(/\D/).empty? and self != ""
#return true
#puts "true"
raise "error from if branch"
else
#return false
#puts "false"
raise "error from else branch"
end

How to convert this if condition to unless?

if array.present?
puts "hello"
end
There is no else part to this.
How to write the above if condition using unless.
I'm asking this question because of this lint error:
Use a guard clause instead of wrapping the code inside a conditional expression
Regarding your comment:
I'm asking this question because of this lint error
Use a guard clause instead of wrapping the code inside a conditional expression
This means that instead of:
def foo(array)
if array.present?
puts "hello"
end
end
You are supposed to use:
def foo(array)
return unless array.present?
puts "hello"
end
See https://github.com/bbatsov/ruby-style-guide#no-nested-conditionals
If this is a Rails question (is it?), you can also use blank?:
def foo(array)
return if array.blank?
puts "hello"
end
There's no reason to.
Remember: unless is the inverse of if (or !if if you rather), and is only intended to make your code easier to read.
Using unless with your expression would be incredibly awkward, because you're now moving the actual body of work to an else statement...
unless array.present?
return
else
puts "hello"
end
...which doesn't make your code any easier to read if you had stuck with a negated if:
if !array.present?
return
else
puts "hello"
end
Don't use unless here. You lose readability in exchange for virtually nothing.
One-liner:
puts "hello" unless !array.present?
However, I would recommend:
puts "hello" if array.present?
unless array.present?
return
else
puts "hello"
end
OP requested one-liner modification:
Pseudocode:
something unless condition
Therefore:
puts "hello" unless !array.present?

How can I make script work in Ruby?

I am new to Ruby.
I need to make this script work:
puts "Do you like cats?"
ask = gets
def ask(n)
if ask == yes
return "I do too"
end
if ask == no
return "Dogs are better"
end
end
puts "#{ask(n)}"
Error message is :
pracif.rb:15:in <main>': undefined local variable or methodn' for
main: Object (NameError)
Here's a script that would work for you :
puts "Do you like cats?"
answer = gets
def ask(n)
if n == 'yes'
return "I do too"
end
if n == 'no'
return "Dogs are better"
end
end
puts ask(answer.downcase.chomp)
Explaination
As the error said you were trying to pass in a variable n which was not defined
Secondly you have a method name ask same as variable name. I've renamed the variable to answer instead
Thirdly, enclose yes and no in quotes
And finally, since you are using gets a \n gets appended like yes\n so none of your conditions would match. So i've used chomp to remove \n. And also used downcase to make input case insensitive.
EDIT
As mentioned by #Jordan in the comments, there is no reason to use string interpolation for the puts statement. So it's enough to call the method directly.
There are a bunch of issues with your code. Try something more like:
def reply(response)
return 'I do too' if response == 'yes'
return 'Dogs are better' if response == 'no'
'Invalid response!'
end
puts 'Do you like cats?'
response = gets().chomp()
puts reply(response)
Pay attention to the variable names. If you keep them descriptive, it is easier to spot mistakes.
Your script has no n local variable defined that you are passing to your ask(n) method at the end.
Rename your ask variable that your script gets from user to answer for example and pass it to your ask method at the end like so:
Updated code to fix other problem I did not see in the first run.
puts "Do you like cats?"
answer = gets.chomp
def ask(n)
(n == 'yes') ? "I do too" : "Dogs are better"
end
puts "#{ask(answer)}"

Ruby 2.1.3 options hash cannot be assigned with fetch

Please explain to me why this is happening:
def resizeImage(event_file, resize_width, resize_height, options = {})
puts options
aspect_ratio = options.fetch(:maintain_aspect_ratio, true)
puts aspect_ratio
"return value"
end
resizeImage('event_file', 'resize_width', 'resize_height', {maintain_aspect_ratio: false} )
{:maintain_aspect_ratio=>false}
false
=> "return value"
I want to set a variable to = the fetch from the hash to make my code more readable. But for some reason it is nil when I call it. It almost looks like the fetch is asynchronous, but this ain't ajax.
This is a pretty elementary problem I know, but so far as I can tell I am doing things just as they are described in more than one guide to using options in ruby methods.
-- Update --
so now I have it returning something else to try to separate the problem. I see that the puts statement for aspect_ratio doesn't actually return anything at all. What is happening?
-- Update2 --
Okay, I got confused. It is returning false. So there is something else wrong in my real method. Thank you for your time, I will accept the most detailed answer but I appreciate both.
Remove this line from your method:
puts aspect_ratio
Your Ruby method is returning to the value of the final statement, i.e. the value of puts.
When you remove that line, then your method will return aspect_ratio.
You actually have the correct structure down, however the final puts in your method is causing the return value to be nil. Ruby utilizes an implicit return, so unless specified, it will return the last value of a method. remove the puts aspect_ratio from the method, or ensure the last line is aspect_ratio and the method will properly return your value
def resizeImage(event_file, resize_width, resize_height, options = {})
puts options
aspect_ratio = options.fetch(:maintain_aspect_ratio, true)
puts aspect_ratio #remove this line
aspect_ratio
end
this can end up being shortened to
def resizeImage(event_file, resize_width, resize_height, options = {})
options.fetch(:maintain_aspect_ratio, true)
end
#joelparkerhendersons answer is correct
Im going to explain whats happening.
Everything in ruby returns something(apart from a tiny minority). It can be forced by using return but by default the last line of the method is returned.
Your method resizeImage returns what puts returns. puts returns nil
Therefore as #joelparkerhendersons suggested remove the puts

Ruby skips items from list tasks

I am trying to make an app which if give the option to type, it types false then it skips the certain element from the list and it jumps to the next executing the same task.
That is the basic idea of the following code:
string["items"].each do |item|
p continue.to_s + "<- item"
begin
Anemone.crawl("http://" + item["displayLink"] + "/") do |anemone|
anemone.on_every_page do |page|
if continue.chomp.to_bool == false
raise "no more please"
end
request = Typhoeus::Request.new(page.url, followlocation: true)
response = request.run
email = /[-0-9a-zA-Z.+_]+#[-0-9a-zA-Z.+_]+\.[a-zA-Z]{2,4}/.match(response.body)
if email.nil?
else
p email
begin
continue = Timeout::timeout(2) do
p "insert now false/nothing"
gets
end
rescue Timeout::Error
continue = "true"
end
end
end
end
rescue
continue = true
next
end
p "---------------------------------------------------------"
end
As the code shows, if the user types false when prompted the app should skip the item and go to the next one. However what it does is: when the user types false the app skips the current item and then doesn't execute any of the code that should be executed for all of the other items except the printing ( the second line of code );
Here is how the output looks like:
$ruby main.rb
"1"
"true<- item"
#<MatchData "support#keycreative.com">
"insert now false/nothing"
false
"true<- item"
"true<- item"
"true<- item"
As I'm doing my best to show after false is entered the code does skip the certain item from the list but it also never ever executes code for the other items as it should since it is an each loop
First I thought that maybe the continue is false however as you can see from the output the continue is true which makes me wonder why does ruby skip my code?
UPDATE
Here is where the to_bool method comes from:
class String
def to_bool()
return true if self == "true"
return false if self == "false"
return nil
end
end
In your last rescue statement add:
rescue => e
puts e.message
continue = true
next
end
and inspect the output. Most likely your code is throwing an exception other than "no more please" (I expect undefined method to_bool for true:TrueClass). Note that using exception for skipping the loop element is a terrible idea. Why can't you just get rid of this rescue and do:
if continue.chomp.to_bool == false
continue = true
next
end
There are a lot of things in this code which makes it very un-ruby-like. If you want to improve it please paste it to StackExchange CodeReview page. (link in the comment).
UPDATE:
My bad, you are in nested loop, so the if statement won't work. You might look at sth similar to raise/rescue bit, namely throw/catch, see example here: How to break from nested loops in Ruby?. I still think you should post it to codereview though for refactoring advises.
As to your actual code (without refactoring). You are calling to_bool method on continue, and in your rescue block you assign true instead of 'true'. Hence your to_bool method raises exception which is then rescued same way as 'no more please' exception.

Resources