I'm trying to figure out how to use the net/ping gem and I have a couple of questions since I've been using it:
Why do you need admin privileges to run ICMP
Does it return true or false? For example:
Net::Ping::ICMP.new("127.0.0.1").ping?# <= true
#So I could do something like this:
ping = Net::Ping::ICMP.new("127.0.0.1")
if ping == true
puts "true"
else
puts "This shouldn't run"
end
#<= true
#or does it return packets received?
#so I could do something like this:
ping = Net::Ping::ICMP.new("127.0.0.1")ping?
if ping =~ /Received = 1/
puts "true"
else
puts "This shouldn't run"
end
#<= true
I'm confused and I can't seem to find anything on google pertaining to how it works: https://www.google.com/search?safe=off&btnG=Search&q=ruby+net%3A%3Aping%3A%3Aicmp+tutorial
If someone could help me it would be greatly appreciated, thank you
This is how ruby evals if:
irb> ping = true
=> true
irb > ping =~ /Received = 1/
=> nil
irb> nil ? "NIL is true" : "NIL is not true"
=> "NIL is not true"
Result of match true is nil, and if nil is false. So, your second example will always outputs "true" (even if .ping? will be false).
And 'admin privileges': you cannot create ICMP packet as normal user. Unless you use /bin/ping which is SUID. (which net/ping gem don't use). `.
Related
The following conditional syntax displays the string 'is true' in irb without using puts
irb(main):001:0> if true
irb(main):002:1> 'is true'
irb(main):003:1> else
irb(main):004:1* 'is false'
irb(main):005:1> end
=> "is true"
...yet when I invoke the same syntax in a script and run it from the command line, it gets ignored. Why?
# Odd behaviour:
puts "Why do only two of the three conditionals print?"
# This doesn't put anything to screen:
if true
'is true_1'
else
'is false'
end
puts "Seriously, why? Or better yet: how?"
# But this does:
if true
puts 'is true_2'
else
puts 'is false'
end
# And this works without "puts":
def truthiness
if 1.send(:==, 1)
'is true_3'
else
'is false'
end
end
puts truthiness
puts "Weird."
When I run this as a script, it displays:
"Why do only two of the three conditionals print?
Seriously, why? Or better yet: how?
is true_2
is true_3
Weird."
FWIW, I am following along with Sandi Metz's talk "Nothing is Something"
https://youtu.be/zc9OvLzS9mU
...and listening to this:
https://youtu.be/AULOC--qUOI
Apologies as I am new to Ruby and trying to wrap my head around how it does what it does.
EDIT:
Useful resources:
http://ruby-doc.org/core-2.3.1/Kernel.html#method-i-puts
https://softwareengineering.stackexchange.com/questions/150824/is-the-puts-function-of-ruby-a-method-of-an-object
The IRB output here is showing the return value of the operation, which is not necessarily what is printed to STDOUT (i.e. the terminal) during execution.
Your script is just throwing the return value away, you would have to do this:
val = if true
'is true_1'
else
'is false'
end
puts val
I expect this code to execute the code block and result in the output "x" and "y", or just to throw a syntax error:
if true
puts "x"
end if
puts "y"
However, the interpreter ignores the if true block and only executes puts "y". If I instead enter the following code:
if true
puts "x"
end if
the interpreter exits with an end-of-input syntax error. Is there a reason why the first snippet is valid code but somehow executing wrong? It would seem to me that there is some error in the parser.
I've confirmed this in Ruby 2.1.2 as well as Ruby 2.1.5.
There are two things playing together here:
The return value of the puts is nil
Ruby is usually clever enough to read the next line if the current command hasn't ended yet.
That means:
if true
puts "x"
end if
puts "y"
is the same than:
if true
puts "x"
end if (puts "y")
Ruby evaluates puts "y" to nil:
if true
puts "x"
end if nil
What leads Ruby to not evaluate the if true block, because if nil acts like if false.
Or in other words: Your example is the same as:
if puts("y") # evaluates to nil (aka is falsey)
if true
puts "x"
end
end
I think what you mean to write is
if true
puts "x"
end
puts "y"
That would produce the output you expect.
Your code is incorrect. The correct code is:
if true
puts "x"
end
puts "y"
Your code tells Ruby to execute the if true ... end block if puts "y" returns true.
puts returns nil, which amounts to false in a condition check, leading to the block not being executed at all.
Your code is effectively saying only to execute the if true block only if puts "y" returns true. Unfortunately, puts returns nil. To end an if statement in Ruby, you simple have to use end. Unlike in Shell Scripting or Visual Basic, there is no specific end statements for different blocks.
Change
if true
puts "x"
end if
puts "y"
to
if true
puts "x"
end
puts "y"
And you'll be golden.
For example, does the presence or absence of do in the following code affect the behavior of the program at all?
while true do
puts "Hi"
break
end
while true
puts "Hi"
break
end
According to The Ruby Programming Language book Section 5.2.1:
The do keyword in a while or until loop is like the then keyword in an
if statement: it may be omitted altogether as long as a newline (or
semicolon) appears between the loop condition and the loop body.
So, no, it won't change the behavior, it's just optional syntax.
Let's find out!
For a quick answer we can look at Ruby's documentation and find http://www.ruby-doc.org/core-2.1.1/doc/syntax/control_expressions_rdoc.html#label-while+Loop which states that
The do keyword is optional.
Ok so these two examples are equivalent but are they identical? They might do the same thing but maybe there's a reason to favor one over the other. We can look at the AST these examples generate and see if there's any difference.
> gem install ruby_parser
> irb
> require 'ruby_parser'
=> true
> with_do = <<-END
while true do
puts "Hi"
break
end
END
=> "while true do\n puts \"Hi\"\n break\nend\n"
> without_do = <<-END
while true
puts "Hi"
break
end
END
=> "while true\n puts \"Hi\"\n break\nend\n"
> RubyParser.new.parse with_do
=> s(:while, s(:true), s(:block, s(:call, nil, :puts, s(:str, "Hi")), s(:break)), true)
> RubyParser.new.parse without_do
=> s(:while, s(:true), s(:block, s(:call, nil, :puts, s(:str, "Hi")), s(:break)), true)
Nope. These two examples execute the exact same instructions so we can pick whichever style we find easier to read. A common preference is to omit the do when possible: https://github.com/bbatsov/ruby-style-guide#no-multiline-while-do
Is there any difference at all between:
something.should == true
and
something.should be_true
?
The convention is: expect(something).to be_true however there is no difference when used properly. Expecting something to == true should only be evaluated against expressions.
See docs: https://github.com/rspec/rspec-expectations#truthiness
Rspec Tests:
describe "is the equation true? " do
let!(:add) { 5+5 == 10 }
it "be_true" do
add.should be_true #passes
end
it "expect be_true" do
expect(add).to be_true #passes
end
it "== true" do
add.should == true #passes
end
end
Update for strings:
A string is not == true so it will fail, but it will pass as be_true because anything except for false or nil is considered truthy. However, this is NOT how you check for a string.
See this example for how to properly check for a value in a string:
str = "happy dance!"
For finding if text is in a string, you would use: expect(str).to include("happy dance!")
The answer supplied to this question is wrong as the below depicts, the first test is a test of equality while the second is a test of truthiness, the first would fail because something != true while the later would pass because anything order than nil or false is truthy in ruby
require 'rspec'
describe "do something" do
let(:something) { "hey" }
it { something.should == true }
it { something.should be_true }
end
No, there is no difference.
The latter is syntactic sugar for the former.
This is my code
pong = /return/.match(cap.array[0])
if pong == "return"
puts "Pong"
end
cap.array[0] is definitely matching /return/ as you can see when I use pp:
#<MatchData "return">
but for some reason, the if statement isn't triggering. Any ideas why it won't match? I tried == and === thinking it could be a type issue, but no joy.
Why two time check?? You can do it in simple way like below:
if /return/ =~ cap.array[0]
puts "pong"
end
For example:
/return/ =~ "Functions return value" #=> 14
/return/ =~ "return" #=> 0
In ruby:
puts "hello" if 0 #=> hello # 0 is not false
So you can avoid multiple checks
Regex#match returns a MatchData object. Thus, its comparison to string fails.
pong = /return/.match('i shall return this')
# cast it to string
if pong.to_s == "return"
# or do this
# if pong[0] == "return"
puts "Pong"
end