Is there a Ruby/Rails function that will strip a string of a certain user-defined character? For example if I wanted to strip my string of quotation marks "... text... "
http://api.rubyonrails.org/classes/ActiveSupport/Multibyte/Chars.html#M000942
I don't know if I'm reinventing the wheel here so if you find a built-in method that does the same, please let me know :-)
I added the following to config/initializers/string.rb , which add the trim, ltrim and rtrim methods to the String class.
# in config/initializers/string.rb
class String
def trim(str=nil)
return self.ltrim(str).rtrim(str)
end
def ltrim(str=nil)
if (!str)
return self.lstrip
else
escape = Regexp.escape(str)
end
return self.gsub(/^#{escape}+/, "")
end
def rtrim(str=nil)
if (!str)
return self.rstrip
else
escape = Regexp.escape(str)
end
return self.gsub(/#{escape}+$/, "")
end
end
and I use it like this:
"... hello ...".trim(".") => " hello "
and
"\"hello\"".trim("\"") => "hello"
I hope this helps :-)
You can use tr with the second argument as a blank string. For example:
%("... text... ").tr('"', '')
would remove all the double quotes.
Although if you are using this function to sanitize your input or output then it will probably not be effective at preventing SQL injection or Cross Site Scripting attacks. For HTML you are better off using the gem sanitize or the view helper function h.
I don't know of one out of the box, but this should do what you want:
class String
def strip_str(str)
gsub(/^#{str}|#{str}$/, '')
end
end
a = '"Hey, there are some extraneous quotes in this here "String"."'
puts a.strip_str('"') # -> Hey, there are some extraneous quotes in this here "String".
You could use String#gsub:
%("... text... ").gsub(/\A"+|"+\Z/,'')
class String
# Treats str as array of char
def stripc(str)
out = self.dup
while str.each_byte.any?{|c| c == out[0]}
out.slice! 0
end
while str.each_byte.any?{|c| c == out[-1]}
out.slice! -1
end
out
end
end
Chuck's answer needs some + signs if you want to remove all extra instances of his string pattern. And it doesn't work if you want to remove any of a set of characters that might appear in any order.
For instance, if we want a string to not end with any of the following: a, b, c, and our string is fooabacab, we need something stronger like the code I've supplied above.
Related
I have two different models: post (it has a content) and keywords (it has the word and the link). I am trying to make a function which would switch words in post content with the same keywords and its link (so it would work as hyperlink) For examples there is a keyword 'Hello' with some link on it and word 'hello', I want 'hello' in post.content to become a hyperlink with link from 'Hello' in keywords.
Here is my function:
def execute
#post = Post.find(params[:post_id])
all_keys = Keyword.all.pluck(:key, :link)
all_keys = all_keys.map.to_h
all_keys = all_keys.transform_keys(&:downcase)
new_content = #post.content.to_s
new_content_downcase = new_content.downcase
all_keys.map { |key, link| new_content_downcase.gsub!(key, "<a href='#{link}'>#{key}</a>") }
#post.content = new_content_downcase
#post.save!
end
Function is easy: I made a hash {key: 'link'} and have #post.content, then I downcase hash keys and #post.content and switch the words in post content with key from hash and link (so it would look like hyperlink).
Everything works fine but the problem is that it switch words in #post.content to lowercase (Hello --> hello). Is there any way to switch compare new_content and new_content_downcase, save the original word AND hyperlink on it?
Just don't downcase the post's content, that's it :) You could use gsub! with the block to make things concise, smth. like the following:
def execute
#post = Post.find(params[:post_id])
keys = Keyword.pluck(:key, :link).to_h.transform_keys(&:downcase)
#post.content.gsub!(/\w+/) do |word|
# We downcase each word when we check for the links presence...
url = keys[word.downcase]
# ... but not when we do replacements.
url ? "<a href='#{url}'>#{word}</a>" : word
end
#post.save!
end
So, your output is all lower case because you've applied #downcase to both your list of keywords and your content. And I assume you did that because you're doing a literal match between the keyword and the content string in your gsub.
One solution is to use a case-insensitive regex instead, :
all_keys.map { |key, link|
#post.content.gsub!(/(#{key})/i, "<a href='#{link}'>\1</a>")
}
Here, I've ignored the downcase and just used #post.content directly (I assume that it's a string so the to_s is redundant).
Then, in the gsub, I replaced the key direct match with a regex. This uses brackets to capture the term that's found for use in the replace term, so that you retain the capitalisation of the source rather than that of the stored keyword. The \1 in the replacement string is how that stored result from the regex gets used.
Fingers crossed that gets you working!
===Edit===
Here's an attempt at doing this properly, updating the entire method. (I'd also not escaped the \1 above, which it needs because it's in double quotes. Sorry about that!)
def export
#post = Post.find(params[:post_id])
_content = #post.content
Keyword.pluck(:key, :link).to_h.each { |_key, _link|
_content.gsub!(/(#{_key})/i, "<a href='#{_link}'>\\1</a>")
}
#post.update(content: _content)
end
Don't add key after \1, as you mention in a comment - the \1 should automatically be replaced with whatever was found by the regex (i.e. the value of key regardless of case).
Also, you shouldn't need to downcase your Keyword entries in any case: the time to do that is when they're created, so you only have to do it once.
How can I check if a string include symbol? It looks confusing to me:
class Beba
def initialize
while true
puts "Qfar emri deshironi ti vnoni bebes?"
##emri = gets.chomp.capitalize
if ##emri.scan(/\d+/).empty? && ##emri.scan(/\/./).empty?
puts "Ti e emertove beben me emrin: #{##emri}"
break
else
puts "Emri nuk mund te jete me numra/simbole, provoni perseri."
end
end
end
end
As you can see, at if##emri.scan(/\d+/).empty? && ##emri.scan(/\/./).empty?, I don't know what to do, like which method can I use for ##emri.scan(/\\.\).empty? to check if my string doesn't include any symbol?
For the specific characters you asked for, you can use this:
##emri.scan(/[!##$%^&*()_+{}\[\]:;'"\/\\?><.,]/).empty?
Will return true if no special character is found.
str !~ /[!##$%^&*()_+{}\[\]:;'"\/\\?><.,]/
returns true if and only if the string str contains none of the characters in the regex's character class (else false is returned).
Its seems you are looking for special characters.
Use something like
"Hel#lo".index( /[^[:alnum:]]/ )
It will return nil if no special charatcters.
[:alnum:] includes all 0-9, a-z, A-Z.
IF YOU WANT TO GO FOR SPECIFIC CHARATCERS
place all characters in a string & create regex like
characters = "!##$%^&*()_+{}[]:;'\"\/?><.,"
regex = /[#{characters.gsub(/./){|char| "\\#{char}"}}]/
& than use this regex to see if any of them exist in string like
if some_string =~ regex
Rails titleize method removes hyphen and underscore, and capitalize method does not capitalize the word comes after hyphen and underscore. I wanted to do something like following:
sam-joe denis-moore → Sam-Joe Denis-Moore
sam-louise o'donnell → Sam-Louise O'Donnell
arthur_campbell john-foo → Arthur_Campbell John-Foo"
What is pattern that need to use on gsub below for this:
"sam-joe denis-moore".humanize.gsub(??) { $1.capitalize }
# => "Sam-Joe Denis-Moore"
Any help is really appreciated
While lurker's answer works, it's far more complicated than it needs to be. As you surmised, you can do this with gsub alone:
INITIAL_LETTER_EXPR = /(?:\b|_)[a-z]/
arr = [ "sam-joe denis-moore",
"sam-louise o'donnell",
"arthur_campbell john-foo" ]
arr.each do |str|
puts str.gsub(INITIAL_LETTER_EXPR) { $&.upcase }
end
# => Sam-Joe Denis-Moore
# Sam-Louise O'Donnell
# Arthur_Campbell John-Foo
Try this:
my_string.split(/([ _-])/).map(&:capitalize).join
You can put whatever delimiters you like in the regex. I used , _, and -. So, for example:
'sam-joe denis-moore'.split(/([ _-])/).map(&:capitalize).join
Results in:
'Sam-Joe Denis-Moore'
What it does is:
.split(/([ _-])/) splits the string into an array of substrings at the given delimiters, and keeps the delimiters as substrings
.map(&:capitalize) maps the resulting array of strings to a new array of strings, capitalizing each string in the array (delimiters, when capitalized, are unaffected)
.join joins the resulting array of substrings back together for the final result
You could, if you want, monkey patch the String class with your own titleize:
class String
def my_titleize
self.split(/([ _-])/).map(&:capitalize).join
end
end
Then you can do:
'sam-joe denis-moore'.my_titleize
=> 'Sam-Joe Denis-Moore'
I have some strings for which i have to check whether it is made up of all special characters in regex i tried something but its not working the way i want any help ?
str = "##%^"
regex = /[\?\<\>\'\,\?\[\]\}\{\=\-\)\(\*\&\^\%\$\#\`\~\{\}\#]/
str.match(regex)
You can do it with
/\A\W*\z/
The \W* matches any non-word character from the beginning (\A) till the end (\z) of string.
See demo:
class String
def onlySpecialChars?
!!self.match(/\A\W*\z/)
end
end
puts "##%^".onlySpecialChars? # true
puts "w##%^".onlySpecialChars? # false
If you have your own set of special characters, just use instead of \W. Just also note you have overescaped your regex, [?<>',?\[\]}{=)(*&^%$#`~{}#-] will suffice.
I'm trying to match a string as such:
text = "This is a #hastag"
raw(
h(text).gsub(/(?:\B#)(\w*[A-Z]+\w*)/i, embed_hashtag('\1'))
)
def embed_hashtag('data')
#... some code to turn the captured hashtag string into a link
#... return the variable that includes the final string
end
My problem is that when I pass '\1' in my embed_hashtag method that I call with gsub, it simply passes "\1" literally, rather than the first captured group from my regex. Is there an alternative?
FYI:
I'm wrapping text in h to escape strings, but then I'm embedding code into user inputted text (i.e. hashtags) which needs to be passed raw (hence raw).
It's important to keep the "#" symbol apart from the text, which is why I believe I need the capture group.
If you have a better way of doing this, don't hesitate to let me know, but I'd still like an answer for the sake of answering the question in case someone else has this question.
Use the block form gsub(regex){ $1 } instead of gsub(regex, '\1')
You can simplify the regex to /\B#(\w+)/i as well
You can leave out the h() helper, Rails 4 will escape malicious input by default
Specify method arguments as embed_hashtag(data) instead of embed_hashtag('data')
You need to define embed_hashtag before doing the substitution
To build a link, you can use link_to(text, url)
This should do the trick:
def embed_hashtag(tag)
url = 'http://example.com'
link_to tag, url
end
raw(
text.gsub(/\B#(\w+)/i){ embed_hashtag($1) }
)
The correct way would be the use of a block here.
Example:
def embed_hashtag(data)
puts "#{data}"
end
text = 'This is a #hashtag'
raw(
h(text).gsub(/\B#(\S+)/) { embed_hashtag($1) }
)
Try last match regexp shortcut:
=> 'zzzdzz'.gsub(/d/) { puts $~[0] }
=> 'd'
=> "zzzzz"