Does Ruby have a some_string.starts_with("abc") method that's built in?
It's called String#start_with?, not String#startswith: In Ruby, the names of boolean-ish methods end with ? and the words in method names are separated with an _. On Rails you can use the alias String#starts_with? (note the plural - and note that this method is deprecated). Personally, I'd prefer String#starts_with? over the actual String#start_with?
Your question title and your question body are different. Ruby does not have a starts_with? method. Rails, which is a Ruby framework, however, does, as sepp2k states. See his comment on his answer for the link to the documentation for it.
You could always use a regular expression though:
if SomeString.match(/^abc/)
# SomeString starts with abc
^ means "start of string" in regular expressions
If this is for a non-Rails project, I'd use String#index:
"foobar".index("foo") == 0 # => true
You can use String =~ Regex. It returns position of full regex match in string.
irb> ("abc" =~ %r"abc") == 0
=> true
irb> ("aabc" =~ %r"abc") == 0
=> false
Related
I have the following URL:
localhost:3000/filter/shoes/color/white
I need to replace all slashes to - except the first slash from localhost:3000/.
The final URL must be:
localhost:3000/filter-shoes-color-white
I've tried some regex with ruby but I didn't have any success.
Thanks.
Here is a regexp that match all the / but the first:
\G(?:\A[^\/]*\/)?+[^\/]*\K\/
So you can do:
"localhost:3000/filter/shoes/color/white".gsub(/\G(?:\A[^\/]*\/)?+[^\/]*\K\//,'-')
#=> "localhost:3000/filter-shoes-color-white"
But it won't work if you have a scheme on your URI.
TL;DR:
regex is:
\/(?<!localhost:3000\/)
Longer one
A famous old Chinese saying is: Teaching how to fishing is better than giving you the fish.
For regex, you can use online regex site such as regex101.com to test immediately with your regex and test string. link
Found other answers from stackoverflow using other key words to describe your situation: Regex for matching something if it is not preceded by something else
Make you own magic.
This is a pretty simple parsing problem, so I question the need for a regular expression. I think the code would probably be easier to understand and maintain if you just iterated through the characters of the string with a loop like this:
def transform(url)
url = url.dup
slash_count = 0
(0...url.size).each do |i|
if url[i] == '/'
slash_count += 1
url[i] = '-' if slash_count >= 2
end
end
url
end
Here is something even simpler using Ruby's String#gsub method:
def transform2(url)
slash_count = 0
url.gsub('/') do
slash_count += 1
slash_count >= 2 ? '-' : '/'
end
end
Using Ruby >= 2.7 with String#partition
Provided you aren't passing in a URI scheme like 'https://' as part of your string, you can do this as a single method chain with String#partition and String#tr. Using Ruby 3.0.2
'localhost:3000/filter-shoes-color-white'.partition(?/).
map { _1.match?(/^\/$/) ? _1 : _1.tr(?/, ?-) }.join
#=> "localhost:3000/filter-shoes-color-white"
This basically relies on the fact that there are no forward slashes in the first array element returned by #partition, and the second element contains a slash and nothing else. You are then free to use #tr to replace forward slashes with dashes in the final element.
If you have an older Ruby, you'll need a different solution since String#partition wasn't introduced before Ruby 2.6.1. If you don't like using character literals, ternary operators, or numbered block arguments (introduced in Ruby 2.7), then you can refactor the solution to suit your own stylistic tastes.
And another way of doing it. No regex and "localhost" lookback needed.
[url.split("/").take(2).join("/"),url.split("/").drop(2).join("-")].join("-")
I'm testing some strings to make sure they start with a letter:
name =~ /\A[a-zA-Z].*/
but since in Ruby this evaluates to either nil or 0 and both cast to false, I need to put an additional .nil? test:
if(name =~ /\A[a-zA-Z].*/).nil? ...
Is this the proper way or am I missing something?
EDIT:
Thanks for the replies, in my ignorance I made wrong assumptions, oversimplified the example. It should read (note the negation):
name !=~ /\A[a-zA-Z].*/
irb(main):001:0> a = "abc"
=> "abc"
irb(main):006:0> (a !=~/\Aabc/)
=> true
irb(main):007:0> (a !=~/\Ab/)
=> true
but since in Ruby this evaluates to either nil or 0 and both cast to false
wrong, only nil (and false, to be precise) are treated as false in conditionals. 0 is treated as true. So
if name =~ /\A[a-zA-Z].*/
is perfectly ok.
About your edited question, you're not allowed to add exclamation sign (!) to any operator to make it negated operator. There's no such operator (BTW, these 'operators' are actually methods) as !=~, so to achieve your goal. you should do:
if !(name =~ /\A[a-zA-Z].*/)
or you can use unless instead:
unless name =~ /\A[a-zA-Z].*/
Python has the following elegant syntax for checking whether one string is a substring of another one:
'ab' in 'abc' # True
Is there an equivalent elegant syntax in Ruby?
I'm aware to the "abc".includes? "ab" Ruby syntax, but I'm wondering whether the inverse syntax exists too (where the first parameter is the substring and the second is the string).
There isn't such method in Ruby standard library, but Rails ActiveSupport provides #.in? method:
1.9.3-p484 :004 > "ab".in? "abc"
=> true
Here is the source code: https://github.com/rails/rails/blob/e20dd73df42d63b206d221e2258cc6dc7b1e6068/activesupport/lib/active_support/core_ext/object/inclusion.rb
Define "elegant".
This does a sub-string search and returns the "hit" if found:
'abc'['ab'] # => "ab"
Using !! converts the value returned to a true/false, so "ab" becomes true:
!!'abc'['ab'] # => true
Knowing that, it's trivial to add it in if you want something closer:
class String
def in?(other)
!!other[self]
end
end
'ab'.in?('abc') # => true
'ab'.in? 'abc' # => true
Or, use require 'active_support/core_ext/object/inclusion' to cherry-pick the Active Suport definition that extends all objects to allow in?. See http://edgeguides.rubyonrails.org/active_support_core_extensions.html#in-questionmark. The upside/downside to that it's modifying all objects.
This code:
/ell/ === 'Hello'
evalutes to 'true' in IRB.
I don't understand why this makes sense logically. Integer === 30 makes sense because 30 is a PART OF the Integer class, but in what way is the string 'Hello' a PART OF /ell/? I don't get it.
Semantically you're saying does the regular expression 'ell' match the string 'Hello'. Since 'Hello' contains the substring 'ell', it is true.
The '===' method is described here:
http://www.ruby-doc.org/core-2.0.0/Regexp.html#method-i-3D-3D-3D
You should not use === for anything in ruby except case equality, find the documentation on Regex#===
Following a regular expression literal with the === operator allows you to compare against a String.
/^[a-z]$/ === "HELLO" #=> false
/^[A-Z]$/ === "HELLO" #=> true
The === the case operator, it is primarily used in case statements and should not really be seen by its own.
case my_string
when /ll/ then puts 'the string migth be hello'
when /x/ then puts 'all i know is that the sting contain x'
else puts 'I have no idea'
end
It can also be used in some other functions such as grep:
array = ['ll', 'aa', 'hello']
p array.grep(/ll/){|x| x.upcase} #=> ["LL", "HELLO"]
Any other use is discouraged and it really does not need to make any sense.
A regular expression describes a language, i.e. a set of strings. The === checks whether the string is a member of that set.
See my answer to a similar question for details.
What is the purpose of the question mark operator in Ruby?
Sometimes it appears like this:
assert !product.valid?
sometimes it's in an if construct.
It is a code style convention; it indicates that a method returns a boolean value (true or false) or an object to indicate a true value (or “truthy” value).
The question mark is a valid character at the end of a method name.
https://docs.ruby-lang.org/en/2.0.0/syntax/methods_rdoc.html#label-Method+Names
Also note ? along with a character acts as shorthand for a single-character string literal since Ruby 1.9.
For example:
?F # => is the same as "F"
This is referenced near the bottom of the string literals section of the ruby docs:
There is also a character literal notation to represent single
character strings, which syntax is a question mark (?) followed by a
single character or escape sequence that corresponds to a single
codepoint in the script encoding:
?a #=> "a"
?abc #=> SyntaxError
?\n #=> "\n"
?\s #=> " "
?\\ #=> "\\"
?\u{41} #=> "A"
?\C-a #=> "\x01"
?\M-a #=> "\xE1"
?\M-\C-a #=> "\x81"
?\C-\M-a #=> "\x81", same as above
?あ #=> "あ"
Prior to Ruby 1.9, this returned the ASCII character code of the character. To get the old behavior in modern Ruby, you can use the #ord method:
?F.ord # => will return 70
It's a convention in Ruby that methods that return boolean values end in a question mark. There's no more significance to it than that.
In your example it's just part of the method name. In Ruby you can also use exclamation points in method names!
Another example of question marks in Ruby would be the ternary operator.
customerName == "Fred" ? "Hello Fred" : "Who are you?"
It may be worth pointing out that ?s are only allowed in method names, not variables. In the process of learning Ruby, I assumed that ? designated a boolean return type so I tried adding them to flag variables, leading to errors. This led to me erroneously believing for a while that there was some special syntax involving ?s.
Relevant: Why can't a variable name end with `?` while a method name can?
In your example
product.valid?
Is actually a function call and calls a function named valid?. Certain types of "test for condition"/boolean functions have a question mark as part of the function name by convention.
I believe it's just a convention for things that are boolean. A bit like saying "IsValid".
It's also used in regular expressions, meaning "at most one repetition of the preceding character"
for example the regular expression /hey?/ matches with the strings "he" and "hey".
It's also a common convention to use with the first argument of the test method from Kernel#test
test ?d, "/dev" # directory exists?
# => true
test ?-, "/etc/hosts", "/etc/hosts" # are the files identical
# => true
as seen in this question here