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}
Related
For my ruby on rails project, I have a model called message which has a to field. I want to implement a wildcard search so that, for example, %545 will bring up all messages ending with 545, 545% will bring up all numbers starting with 545, %545% will bring up all messages including 545.
I have a query like Message.where("to like ?", str) where str is the string to match, e.g. %545, %545%, 545%...etc.
Everything works but I'm concerned about SQL injection attack. So I want to do a regex matching for str so that it only allows % and numbers to pass through. So I want strings like %545, %545%, 545% to pass, but not abc, %545a, a545%, %54a5% to pass.
I've tried str.scan(/.*?(\d+%)/) but that doesn't work.
Thanks.
You are correctly using placeholders, so you are protected from SQL injection attacks already. Rails will escape any unsafe characters in the pattern; you don't need to take any further action.
If you still want to strip characters other than digits and %, you can use Ruby's String#delete method:
str.delete('^1-9%')
The '^1-9%' argument means "Delete every character that is not 1 to 9 or %". (n.b. you cannot use \d here, because #delete doesn't understand regular expression meta characters.)
See https://ruby-doc.org/core-2.5.3/String.html#method-i-delete.
I have user controller input like so (the length and # of items may change):
str = "['honda', 'toyota', 'lexus']"
I would like to convert this into an array, but I'm struggling to find the best way to do so. eval() does exactly what I need, but it is not very elegant and is dangerous in this case, since it's user controller input.
Another way is:
str[1..-2].split(',').collect { |car| car.strip.tr("'", '') }
=> ["honda", "toyota", "lexus"]
But this is also not very elegant. Any suggestions that are more 'Rubyish'?
You could use a regular expression:
# match (in a non-greedy way) characters up to a comma or `]`
# capture each word as a group, and don't capture `,` or `]`
str.scan(/'(.+?)'(?:,|\])/).flatten
Or JSON.parse (but accounting for the fact that single quotes are in fact technically not allowed in JSON):
JSON.parse( str.tr("'", '"') )
JSON.parse probably has a small edge over the regexp in terms of performance, but if you're expecting your users to do single quote escaping, then that tr is going to mess things up. In this case, I'd stick with the regexp.
The JSON.parse looks more correct, but here is another alternative:
str.split(/[[:punct:] ]+/).drop(1)
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/
I am using ruby on rails
I have
article.id = 509969989168Q000475601
I would like the output to be
article.id = 68Q000475601
basically want to get rid of all before it gets to 68Q
the numbers in front of the 68Q can be various length
is there a way to remove up to "68Q"
it will always be 68Q and Q is always the only Letter
is there a way to say remove all characters from 2 digits before "Q"
I'd use:
article.id[/68Q.*/]
Which will return everything from 68Q to the end of the string.
article.id.match(/68Q.+\z/)[0]
You can do this easily with the split method:
'68Q' + article.id.split('68Q')[1]
This splits the string into an array based on the delimiter you give it, then takes the second element of that array. For what it's worth though, #theTinMan's solution is far more elegant.
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"