Regular expression to explode the URLs - ruby-on-rails

When I am trying to explode the url from one string, its not returning the actual URL. Please find the def I have used
def self.getUrlsFromString(str="")
url_regexp = /(?:http|https):\/\/[a-z0-9]+(?:[\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(?:(?::[0-9]{1,5})?\/[^\s]*)?/ix
url = str.split.grep(url_regexp)
return url
rescue Exception => e
DooDooLogger.log(e.message,e)
return ""
end
when I do self.getUrlsFromString(" check this site...http://lnkd.in/HjUVii") it's returning
site...http://lnkd.in/HjUVii
Instead of
http://lnkd.in/HjUVii

It's because grep in Array class returns an array of every element for element === pattern, so
str.split.grep(/http/ix)
will return ["site...http://lnkd.in/HjUVii"] too.
You can try instead of
str.split.grep(url_regexp)
something like this:
url_regexp.match(str).to_s

Should not you use something much simpler as regex like:
/((http|https):[^\s]+)/

If you want to find all occurences in a string, you could use String#scan:
str = "check these...http://lnkd.in/HjUVii http://www.google.com/"
str.scan(url_regexp)
=> ["http://lnkd.in/HjUVii", "http://www.google.com/"]

Related

Is there a method like "ILIKE" I can use in a Rails conditional statement?

I want to perform an action if a string is contained, non-case-sensitively, in another string.
So my if statement would look something like this:
#a = "search"
if #a ILIKE "fullSearch"
#do stuff
end
You can use the include? method. So in this case:
#var = 'Search'
if var.include? 'ear'
#action
end
Remember include? method is case-sensitive. So if you use something like include? 'sea' it would return false. You may want to do a downcase before calling include?()
#var = 'Search'
if var.downcase.include? 'sea'
#action
end
Hope that helped.
There are many ways to get there. Here are three:
'Foo'.downcase.include?('f') # => true
'Foo'.downcase['f'] # => "f"
Those are documented in the String documentation which you need to become very familiar with if you're going to program in Ruby.
'Foo'[/f/i] # => "F"
This is a mix of String's [] slice shortcut and regular expressions. I'd recommend one of the first two because they're faster, but for thoroughness I added it because people like hitting things with the regex hammer. Regexp contains documentation for /f/i.
You'll notice that they return different things. Ruby considers anything other than false or nil as true, AKA "truthiness", so all three are returning a true value, and, as a result you could use them in conditional tests.
You can use a regexp with i option. i for insensitive I think.
a = "fullSearch"
a =~ /search/i
=> 4
a =~ /search/
=> nil
Or you could downcase your string and check if it's present in the other
a = "fullSearch"
a.downcase.include?('search')
=> true

Ruby (Rails) gsub: pass the captured string into a method

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"

How to use #{} without converting array to string

I have this code block.
query = ['an','array']
#a = params[:action] == 'show' ? "paid" : "paid_students"
variable = "Student.#{#a}(#{query})"
eval(a)
But when I run this I am getting "variable" value as
Student.paid('anarray')
The array is converted to string.How can I avoid this. pls help
The #{} symbol is string interpolation. Its entire purpose is to turn an object into a string and interpolate it into another string. If you want to turn it into a different kind of string, you can certainly do that. For example, if you want to turn it into the string "[1, 2, 3]", you can do variable = "Student.#{#a}(#{query.inspect})".
But a better way to do what you're trying to do would be this:
query = ['an','array']
#a = params[:action] == 'show' ? :paid : :paid_students
Student.send(#a, query)
For more information, see the Ruby Object#send documentation.
variable = "Student.#{#a}(query)"
Doesn't work?

Append query string to url

I have a callback url string params[:callback] and I need to append a query string "&result=true" and redirect the user. The better way I found of doing this is using addressable but I think the code is too big for task like this especially when we are talking about ruby:
callback = Addressable::URI.parse(params[:callback])
query = callback.query_values
query[:result] = 'true'
callback.query_values = query
redirect_to callback.to_s
Is there a more elegant way of getting the same result as this snippet?
I wan't to bring update to this topic, because any of the solutions didn't work me.
The reason being, that it seems that callback.query_values returns Nil if the actual url doesn't have existing query values.
Therefore if you have urls such as: http://www.foo.com and http://www.foo.com?bar=1 you should use the following code:
url = "http://www.foo.com" # or params[:callback] obviously. :)
callback = Addressable::URI.parse(url)
callback.query_values = (callback.query_values || {}).merge({
result: true
})
redirect_to callback.to_s
Cheers.
if you don't need any URL validations you can do this (looks a little bit dirty):
url = params[:callback]
redirect_to url + (url.include?('?') ? '&' : '?') + 'result=true'
otherwise you have to use either some external library (like Addressable) or URI module from standard library
callback.query_values = callback.query_values.merge({"result" => "true"})
I think you're pretty close to optimal. you could crush out a line or two,
but it doesn't really gain you anything.
callback = Addressable::URI.parse(params[:callback])
callback.query_values = callback.query_values.merge {:results => 'true' }
redirect_to callback.to_s
If the callback is always inside your application, you might have some other options with varying degrees of coolness, but you didn't specify if that was the case or not.
years later, I find a better solution of this problem.
Get the value from the super first, then do any tweaks we need using Addressable
def url_for(options={})
val = super
if params[:locale].present?
parsed = Addressable::URI.parse(val)
query_array = parsed.query_values(Array) || []
query_array << ['locale', params[:locale]]
parsed.query_values = query_array
val = parsed.to_s
end
val
end
Let me offer this one modestly. I suggest using only strings for query parameters keys and values (like Arye noted) . Also, NilClass instances have a to_h method, which allows to remove some brackets:
callback = Addressable::URI.parse(params[:callback])
callback.query_values = callback.query_values.to_h.merge("result" => "true")
redirect_to callback.to_s
You can try with merge
request.parameters.merge({:result => true})
this will add your parameter to the ones already defined.

Strip method for non-whitespace characters?

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.

Resources