Backslash in Ruby conditional statement - ruby-on-rails

I was browsing some code and spotted this:
stem = ""
answer = ""
return if stem.nil? || answer.nil? || \
stem.question == answer.question
What is the \ for? I know \ is used in strings, but I've never seen a use-case for this before. Is this a syntax error or some advanced ruby syntax? Am I missing something?

It's a useless line-continuation character.
The question "is it a syntax error" seems pretty simple to discover.

\ is used to indicate line continuation in ruby. Using \ will strip the \n (newline) character.
Example (Using string):
Without \:
2.1.2-perf :018 > s = "test this
2.1.2-perf :019"> out"
=> "test this\nout"
With \:
2.1.2-perf :020 > s = "test this \
2.1.2-perf :021"> out"
=> "test this out"
Example (without using string):
Without \:
2.1.2-perf :043 > return "test" if true && false &&
2.1.2-perf :044 > true
=> nil
With \:
2.1.2-perf :045 > return "test" if true && false && \
2.1.2-perf :046 > true
=> nil
In your case, it wouldn't matter, but it is not a syntax error.
From the doc:
Ruby programs are sequence of expressions. Each expression are delimited by semicolons(;) or newlines. Backslashes at the end of line does not terminate expression.

Related

In Ruby 1.9.3, check if the user input is a directory

#!/usr/bin/ruby
puts "Please enter the path-name of the directory:"
p = STDIN.gets
isdir = File.directory?(p)
puts "#{isdir} #{p}"
it always return me a false! even though I know the user input is a directory. I think (p) is not working as a parameter. So i think its saying that p is not a directory not the user input for example "/usr/bin/". any help?
Using p = STDIN.gets '\n' was getting appended. Instead you can use gets.chomp. Also you need to use File.expand_path. Check the example below.
# My irb
1.9.3-p545 :002 > p = gets.chomp
~/.ssh
=> "~/.ssh"
1.9.3-p545 :003 > File.directory?(p)
=> false
1.9.3-p545 :004 > File.exists? File.expand_path(p)
=> true
The p value is not strictly equal to what you expect it to be. It contains \n at the end:
# in my irb:
1.9.3p392 :010 > p = STDIN.gets
/home/
=> "/home/\n"
1.9.3p392 :011 > isdir = File.directory?(p)
=> false
1.9.3p392 :012 > isdir = File.directory?(p.strip)
=> true
The strip method:
Strips entire range of Unicode whitespace from the right and left of the string.
Source: http://apidock.com/rails/ActiveSupport/Multibyte/Chars/strip

escape double quotes in ruby

How can I replace double-quotes to &quote; in a string?
This is what I have tried:
1.9.3-p362 :009 > a = "\"That's it\", she said."
=> "\"That's it\", she said."
1.9.3-p362 :010 > a.tr('"', "&quote;")
=> "&That's it&, she said."
As you see instead of &quotes; I only get &, any idea?
use gsub instead
a.gsub(/\"/, "&quote;")
# without regex as noted by hirolau
a.gsub("\"", "&quote;")
# => "&quote;That's it&quote;, she said."

Simple regex check failing in a rails model

I have a check of the following type
validates :callback_handle, :format => { :with => /[_0-9a-zA-Z]+/ix }, :unless => "callback.nil?"
I do not want any non 0-9, a-z A-Z characters to pass. So i set callback_handle to
"!alksjda" (note ! at the begining).
This test does not fail. What am I doing wrong?
I tried a few things on irb: This is what I got:
1.9.2-p320 :001 > a = "!askldjlad"
=> "!askldjlad"
1.9.2-p320 :002 > a =~ /[_0-9a-zA-Z]+/ix
=> 1
1.9.2-p320 :003 > a = "askldjlad"
=> "askldjlad"
1.9.2-p320 :004 > a =~ /[_0-9a-zA-Z]+/ix
=> 0
I thought it would return false or nil on failure to find the match.
Can someone tell me what is wrong here in my understanding?
EDIT:
I figured out that =~ will return position of a match.
So the question becomes How do I not allow something that has any other character to not match?
Your regular expression is still able to match, because there is at least 1 character in your string that is alpha-numeric. If you want to make sure that the entire string matches then you should define the beginning and end of the match.
Old:
a =~ /[_0-9a-zA-Z]+/ix
This is saying "match at least one of these characters somewhere in a.
New:
a =~ /\A[_0-9a-zA-Z]+\z/ix
This is saying "start at the beginning of the string, then match at least 1 of only these characters, followed by the end of the string" in a.
Your regex just asks that your string contains 1 or more valid characters ... this should fix it :
validates :callback_handle, :format => { :with => /^[_0-9a-zA-Z]+$/ix }, :unless => "callback.nil?"

Ruby: How to remove trailing backslashes from a string?

I have a string like
"car\"
which I will be storing in postgres db. I want to remove the backslash from the string before saving. Is there a way I can do that in ruby or in postgres? When I try to remove it in ruby, it considers the quote after the backslash as an escape character.
See following code:
1.9.3p125 :022 > s = "cat\\"
=> "cat\\"
1.9.3p125 :023 > puts s
cat\
=> nil
1.9.3p125 :024 > s.chomp("\\")
=> "cat"
1.9.3p125 :025 >
People don't do this much, but Ruby's String class supports:
irb(main):002:0> str = 'car\\'
=> "car\\"
irb(main):003:0> str[/\\$/] = ''
=> ""
irb(main):004:0> str
=> "car"
It's a conditional search for a trailing '\', and replacement with an empty string.
To remove a trailing backslash:
"car\\".gsub!(/\\$/, "")
Note that the backslash has to be escaped itself with a backslash.
puts '"car\"'.gsub(/\\(")?$/, '\1')
that will do it,
but, is the trailing slash always at the en followed by a quote?
See what says the
str.dump
operation, and then try to operate on that.

How to determine if there is a match an return true or false in rails?

I want to create a test that returns either true or false for email handling.
For now, if the email address starts with r+ then it's true otherwise it's false. This will help our server ignore a lot of the SPAM we are getting hit with.
Examples:
r+kldslkadslkadslk#site.com .. true
r+123123312#site.com .. true
vigraaaa#site.com .. FALSE
What's the most efficient way to handle this with Rails/ruby/regex?
Thanks
GOAL
Is a one liner in rails/ruby with:
ABORT if XXXXX == 0
This will match:
/^r\+.*#site.com$/
Examples:
>> 'r+kldslkadslkadslk#site.com' =~ /^r\+.*#site.com$/ #=> 0
>> 'vigraaaa#site.com' =~ /^r\+.*#site.com$/ #=> nil
Since everything that isn't nil or false is truthy in Ruby, you can use this regex in a condition. If you really want a boolean you can use the !! idiom:
>> !!('vigraaaa#site.com' =~ /^r\+.*#site.com$/) #=> false
>> !!('r+kldslkadslkadslk#site.com' =~ /^r\+.*#site.com$/) #=> true
If you're in Rails, there's a starts_with? method on strings:
"foo".starts_with?('f') # => true
"foo".starts_with?('g') # => false
Outside of Rails, regexes are a reasonable solution:
"foo" =~ /^f/ # => true
"foo" =~ /^g/ # => false
Because Ruby uses truthiness in if statements, if you do end up using regexes, you can just use the return value to switch:
if "foo" =~ /^f/
puts "Was true!"
else
puts "Was false!"
end
If you're writing a method and want to return a boolean result, you could always use the double bang trick:
def valid_email?
!!("foo" =~ /^f/)
end
Rubular (rubular.com) is a good site for testing Ruby regexes pre-1.9. (1.9's regexes added things like lookahead.)
If you don't want to use an "!!" operator:
!!("foo" =~ /^f/)
you could use a ternary operator (might look more obvious):
"foo" =~ /^f/ ? true : false
You can use the '===' operator as well
/f/ === 'foo' #=> true
/f/ === 'bat' #=> false
Note: The regex part is on the left:
/YOUR_REGEX/ === 'YOUR_STRING'
Regexp#match? was added to Ruby-2.4.0. See Regexp#match documentation.
irb(main):001:0> "ack!".match? /a(b|c)/
=> true
irb(main):002:0> "add".match? /a(b|c)/
=> false

Resources