gsub { $1.upcase } ? Is equivalent to .capitalize? - ruby-on-rails

I found in the legacy code the following:
"myString".sub(/^(.)/) {$1.upcase} seems very weird. While executing in IRB, I got the same result as "myString".capitalize
Wasn't able to find the documentation... so ended up on SO

Not exactly,
"myString".capitalize
#=> "Mystring"
"myString".sub(/^(.)/) {$1.upcase}
#=> "MyString"
From the docs for capitalize
Returns a copy of str with the first character converted to uppercase and the remainder to lowercase. Note: case conversion is effective only in ASCII region.

sub accepts an optional block instead of a replacement parameter. If given, it places the sub-matches into global variables, invokes the block, and returns the matched portion of the string with the block's return value.
The regular expression in question finds the first character at the beginning of a line. It places that character in $1 because it's contained in a sub-match (), invokes the block, which returns $1.upcase.
As an aside, this is a brain-dead way of capitalizing a string. Even if you didn't know about .capitalize or this code is from before .capitalize was available (?), you could still have simply done myString[0] = myString[0].upcase. The only possible benefit is the .sub method will work if the string is empty, where ""[0].upcase will raise an exception. Still, the better way of circumventing that problem is myString[0] = myString[0].upcase if myString.length > 0

Both are not exactly same. sub is used to replace the first occurrence of the pattern specified, whereas gsub does it for all occurrences (that is, it replaces globally).
In your question, regular expression is the first character i.e., $1 and replaces with $1.upcase.
CODE :
"myString".sub(/^(.)/) {$1.upcase}
OUTPUT :
"MyString"
CODE :
"myString".capitalize
OUTPUT :
"Mystring"

Related

How to use gsub with array element in ruby

I am trying to remove some speicial character from array but it showing error
undefined method gsub! for array
def get_names
Company.find(#company_id).asset_types.pluck(:name).reject(&:nil?).gsub!(/([^,-_]/, '').map(&:downcase)
end
As it was said arrays don't respond to gsub!. An array is a collection of items that you might process. To achieve what you want you should call gsub on each item. Notice the difference between gsub! and gsub methods. gsub! will modify a string itself and might return nil whereas gsub will just return a modified version of a string. In your case, I'd use gsub. Also, reject(&:nil?) might be replaced with compact, it does the same thing. And you can call downcase inside the same block where you call gsub.
asset_types = Company.find(#company_id).asset_types.pluck(:name).compact
asset_types.map do |asset_type|
asset_type.gsub(/([\^,-_])/, '').downcase
end
UDP
Your regexp /([^,-_])/ means replace all characters that are not ,, - or _. See the documentation
If the first character of a character class is a caret (^) the class is inverted: it matches any character except those named.
To make it work as expected you should escape ^. So the regexp will be /([\^,-_])/.
There is a website where you can play with Ruby's regular expressions.
To put it simply without getting into other potential issues with your code, you are getting the error because gsub is only a valid Method in Class: String. You are attempting to use it in Class: Array.
If you want to use gsub on your individual array elements, you must do 2 things:
Convert your individual array elements to strings (if they aren't strings already).
Use gsub on those individual strings
The above can be done any number of ways but those basics should directly address your core question.
For what its worth, I would typically use something like this:
new_array = old_array.map {|element| element.to_s.gsub(*args)}
In fact, you could simply change the last section of your existing code from:
....gsub(*args).map(&:downcase)
to:
....map {|x| x.to_s.gsub(*args).downcase}

How to simply find substring in string?

For example string.find not work correct:
print ( string.match("Test/(", "Test/(") )
second argument is submitted as regexp, not simple string.
print(string.match("Test/(", "Test/("))
Will cause the error message
unfinished capture
"Test/(" is not a valid Lua string pattern.
( is one of the magic characters ^$()%.[]*+-? which have to be escaped by prepending % because they otherwise have a special meaning in defining patterns. ( starts a capture. As it is not followed by ) to end it your pattern contains an unfinished capture.
Use "Test/%(" instead to include the parenthesis into your search and avoid the error message.
Please refer to the Lua Reference Manual - Patterns for further details.
Is this what you're looking for?
string.sub(s, i [, j])s:sub(i [,j])
Return a substring of the string passed. The substring starts at i. If the third argument j is not given, the substring will end at the end of the string. If the third argument is given, the substring
ends at and includes j
You can find documentation of the functions here

Rails strip all except numbers commas and decimal points

Hi I've been struggling with this for the last hour and am no closer. How exactly do I strip everything except numbers, commas and decimal points from a rails string? The closest I have so far is:-
rate = rate.gsub!(/[^0-9]/i, '')
This strips everything but the numbers. When I try add commas to the expression, everything is getting stripped. I got the aboves from somewhere else and as far as I can gather:
^ = not
Everything to the left of the comma gets replaced by what's in the '' on the right
No idea what the /i does
I'm very new to gsub. Does anyone know of a good tutorial on building expressions?
Thanks
Try:
rate = rate.gsub(/[^0-9,\.]/, '')
Basically, you know the ^ means not when inside the character class brackets [] which you are using, and then you can just add the comma to the list. The decimal needs to be escaped with a backslash because in regular expressions they are a special character that means "match anything".
Also, be aware of whether you are using gsub or gsub!
gsub! has the bang, so it edits the instance of the string you're passing in, rather than returning another one.
So if using gsub! it would be:
rate.gsub!(/[^0-9,\.]/, '')
And rate would be altered.
If you do not want to alter the original variable, then you can use the version without the bang (and assign it to a different var):
cleaned_rate = rate.gsub!(/[^0-9,\.]/, '')
I'd just google for tutorials. I haven't used one. Regexes are a LOT of time and trial and error (and table-flipping).
This is a cool tool to use with a mini cheat-sheet on it for ruby that allows you to quickly edit and test your expression:
http://rubular.com/
You can just add the comma and period in the square-bracketed expression:
rate.gsub(/[^0-9,.]/, '')
You don't need the i for case-insensitivity for numbers and symbols.
There's lots of info on regular expressions, regex, etc. Maybe search for those instead of gsub.
You can use this:
rate = rate.gsub!(/[^0-9\.\,]/g,'')
Also check this out to learn more about regular expressions:
http://www.regexr.com/

How to identify a hash-tagged word in a string

I want to find the word that has been tagged in a string and set a variable to that tag
message = '#Identifier with some text'
tag = message.scan(/#\w+/)
This returns an array of the tags. I'm expecting there to be only 1 tagged word in the string so I would like it to return a word and not an array.
The text is generally not very long as it is being sent via sms.
Efficiency and speed of the function is obviously NB.
Thanks for the help.
Do as below uusing String#[]
If a Regexp is supplied, the matching portion of the string is returned. If a capture follows the regular expression, which may be a capture group index or name, follows the regular expression that component of the MatchData is returned instead.
message = '#Identifier with some text'
message[/#\w+/] # => "#Identifier"
Just remember : \w+ means [a-zA-Z0-9_] . If you have any more characters followed by # symbol use an explicit character class. Like suppose -,+ etc can be present also, so use the explicit character class [a-zA-Z0-9_+-] as an example - message[/#[a-zA-Z0-9_+-]+/]

Lua string.gsub without printing match count

Frustratingly, any my previous Lua tries went in extensive Google searching of more/less same Lua resources, and then resulted in some multi-line code to get basic things, which i.e. I get from Python with simple command.
Same again, I want to replace substring from string, and use i.e.:
string.gsub("My string", "str", "th")
which results in:
My thing 1
I imagine replacement count can be useful, but who would expect it by default, and without option to suppress it, but maybe I miss something?
How to print just string result, without counter?
Enclose in parentheses: (string.gsub("My string", "str", "th")).
The results are only a problem because you are using print, which takes multiple parameters. Lua allows multiple assignments, so normally the code would look like
newstr, n = string.gsub("My string", "str", "th")
but the count is only provided if there is a place to put it, so
newstr = string.gsub("My string", "str", "th")
is also fine, and causes the count to be discarded. If you are using print directly (the same applies to return) then you should enclose the call in parentheses to discard all but the first result.

Resources