Extracting a part of a string in Ruby - ruby

I know this is an easy question, but I want to extract one part of a string with rails.
I would do this like Java, by knowing the beginning and end character of the string and extract it, but I want to do this by ruby way, that's why I need your help.
My string is:
STACK OVER AND FLOW
And I want the numerical values between quotation marks => 99999 and the value of the link => STACK OVER AND FLOW
How should I parse this string in ruby ?
Thanks.

If you need to parse html:
> require 'nokogiri'
> str = %q[STACK OVER AND FLOW]
> doc = Nokogiri.parse(str)
> link = doc.at('a')
> link.text
=> "STACK OVER AND FLOW"
> link['href'][/(\d+)/, 1]
=> "99999"
http://nokogiri.org/

This should work if you have only one link in string
str = %{STACK OVER AND FLOW }
num = str.match(/href=".*?'(\d*)'.*?/)[1].to_i
name = str.match(/>(.*?)</)[1].strip

Way to get both at a time:
str = "STACK OVER AND FLOW "
num, name = str.scan(/launchRemote\('(\d+)'[^>]+>\s*(.*?)\s*</).first
# => ["99999", "STACK OVER AND FLOW"]

Related

String Include is not matching

I'm having an issue where a string link that has .pdf is not matching with include? in ruby. Example code
link = somelink.pdf
puts link.include?(".pdf")
Output when I run the program.
http://somelink.com/somepdf.pdf
false
Try converting to string first
link = somelink.pdf
puts link.to_s.include?(".pdf")
OR
File.extname(link.to_s) == ".pdf"

Extract url params in ruby

I would like to extract parameters from url. I have following path pattern:
pattern = "/foo/:foo_id/bar/:bar_id"
And example url:
url = "/foo/1/bar/2"
I would like to get {foo_id: 1, bar_id: 2}. I tried to convert pattern into something like this:
"\/foo\/(?<foo_id>.*)\/bar\/(?<bar_id>.*)"
I failed on first step when I wanted to replace backslash in url:
formatted = pattern.gsub("/", "\/")
Do you know how to fix this gsub? Maybe you know better solution to do this.
EDIT:
It is plain Ruby. I am not using RoR.
As I said above, you only need to escape slashes in a Regexp literal, e.g. /foo\/bar/. When defining a Regexp from a string it's not necessary: Regexp.new("foo/bar") produces the same Regexp as /foo\/bar/.
As to your larger problem, here's how I'd solve it, which I'm guessing is pretty much how you'd been planning to solve it:
PATTERN_PART_MATCH = /:(\w+)/
PATTERN_PART_REPLACE = '(?<\1>.+?)'
def pattern_to_regexp(pattern)
expr = Regexp.escape(pattern) # just in case
.gsub(PATTERN_PART_MATCH, PATTERN_PART_REPLACE)
Regexp.new(expr)
end
pattern = "/foo/:foo_id/bar/:bar_id"
expr = pattern_to_regexp(pattern)
# => /\/foo\/(?<foo_id>.+?)\/bar\/(?<bar_id>.+?)/
str = "/foo/1/bar/2"
expr.match(str)
# => #<MatchData "/foo/1/bar/2" foo_id:"1" bar_id:"2">
Try this:
regex = /\/foo\/(?<foo_id>.*)\/bar\/(?<bar_id>.*)/i
matches = "/foo/1/bar/2".match(regex)
Hash[matches.names.zip(matches[1..-1])]
IRB output:
2.3.1 :032 > regex = /\/foo\/(?<foo_id>.*)\/bar\/(?<bar_id>.*)/i
=> /\/foo\/(?<foo_id>.*)\/bar\/(?<bar_id>.*)/i
2.3.1 :033 > matches = "/foo/1/bar/2".match(regex)
=> #<MatchData "/foo/1/bar/2" foo_id:"1" bar_id:"2">
2.3.1 :034 > Hash[matches.names.zip(matches[1..-1])]
=> {"foo_id"=>"1", "bar_id"=>"2"}
I'd advise reading this article on how Rack parses query params. The above works for your example you gave, but is not extensible for other params.
http://codefol.io/posts/How-Does-Rack-Parse-Query-Params-With-parse-nested-query
This might help you, the foo id and bar id will be dynamic.
require 'json'
#url to scan
url = "/foo/1/bar/2"
#scanning ids from url
id = url.scan(/\d/)
#gsub method to replacing values from url
url_with_id = url.gsub(url, "{foo_id: #{id[0]}, bar_id: #{id[1]}}")
#output
=> "{foo_id: 1, bar_id: 2}"
If you want to change string to hash
url_hash = eval(url_with_id)
=>{:foo_id=>1, :bar_id=>2}

Ruby regular expression to extract key values

I have string like below
case1:
str = "type=\"text/xsl\" href=\"http://skdjf.sdjhshf/CDA0000=.xsl\""
case2:
str = "href=\"http://skdjf.sdjhshf/CDA0000=.xsl\" type=\"text/xsl\""
I need to extract the values like
type -> text/xsl
href -> http://skdjf.sdjhshf/CDA0000=.xsl
Here is my regular expression that fails.
str.match(/type="(.*)"/)[1]
#this works in second case
=>"text/xsl"
str.match(/http="(.*)"/)[1]
#this works in first case
=>"http://skdjf.sdjhshf/CDA0000=.xsl"
In failure cases the whole string is matched.
Any idea?
Agree with John Watts comment. Use something like nokogiri to parse XML - it is a breeze. If you still want to stick with regex parsing you could do something like:
str.split(' ').map{ |part| part.match( /(.+)="(.+)"/ )[1..2] }
and you will get results as below:
> str = "type=\"text/xsl\" href=\"http://skdjf.sdjhshf/CDA0000=.xsl\""
=> "type=\"text/xsl\" href=\"http://skdjf.sdjhshf/CDA0000=.xsl\""
> str2 = "href=\"http://skdjf.sdjhshf/CDA0000=.xsl\" type=\"text/xsl\""
=> "href=\"http://skdjf.sdjhshf/CDA0000=.xsl\" type=\"text/xsl\""
> str.split(' ').map{ |part| part.match( /(.+)="(.+)"/ )[1..2] }
=> [["type", "text/xsl"], ["href", "http://skdjf.sdjhshf/CDA0000=.xsl"]]
> str2.split(' ').map{ |part| part.match( /(.+)="(.+)"/ )[1..2] }
=> [["href", "http://skdjf.sdjhshf/CDA0000=.xsl"], ["type", "text/xsl"]]
that you can put in a hash or wherever wou want to have it.
With nokogiri you can get hold of a node and then do something like node['href'] in your case. Probably much easier.

Working with hashes in ruby on rails

My apologizes if this has been covered before; I searched and searched but I did not find an answer...
I have the following hash:
input = '{"names":[{"name":"a1","id":1},{"name":"b2","id":2}]}'
I'd like to extract and display the values- one per line. When I run it from rails console, I get the correct results:
>> r1 = ActiveSupport::JSON.decode(input)
=> {"names"=>[{"name"=>"a1", "id"=>1}, {"name"=>"b2", "id"=>2}]}
>> r1["names"].each do |x|
?> puts "#{x["name"]}"
>> end
a1
b2
=> [{"name"=>"a1", "id"=>1}, {"name"=>"b2", "id"=>2}]
THe question is how do I replicate this behavior in my rails application? I tried the following method, but only one value is return in the browser:
module PageHelper
def testcall()
input = '{"names":[{"name":"a1","id":1},{"name":"b2","id":2}]}'
r1 = ActiveSupport::JSON.decode(input)
r1["names"].each do |a|
return "Name: #{a["name"]}\n"
end
end
TIA!
returning terminates the loop after the first element. Try appending the output to a string (including newlines \n in-between) in the loop, and then return that string after the loop.
As #Irfy said, this is happening because of return statement. Following code works,
module PageHelper
def testcall()
input = '{"names":[{"name":"a1","id":1},{"name":"b2","id":2}]}'
r1 = ActiveSupport::JSON.decode(input)
r1["names"].map{|hash| hash["name"]}
end
end

ruby string splitting problem

i have this string:
"asdasda=asdaskdmasd&asmda=asdasmda&ACK=Success&asdmas=asdakmsd&asmda=adasda"
i want to get the value after between the ACK and the & symbol, the value between the ACK and the & symbol can be changed...
thanks
i want the solution in ruby.
require "cgi"
query_string = "asdasda=asdaskdmasd&asmda=asdasmda&ACK=Success&asmda=asdakmsd"
parsed_query_string = CGI.parse(query_string)
#=> { "asdasda" => ["asdaskdmasd"],
# "asmda" => ["asdasmda", "asdakmsd"],
# "ACK" => ["Success"] }
parsed_query_string["ACK"].first
#=> "Success"
If you also want to reconstruct the query string (especially together with the rest of a URL), I would recommend looking into the addressable gem.
require "addressable/uri"
# Note the leading '?'
query_string = "?asdasda=asdaskdmasd&asmda=asdasmda&ACK=Success&asmda=asdakmsd"
parsed_uri = Addressable::URI.parse(query_string)
parsed_uri.query_values["ACK"]
#=> "Success"
parsed_uri.query_values = parsed_uri.query_values.merge("ACK" => "Changed")
parsed_uri.to_s
#=> "?ACK=Changed&asdasda=asdaskdmasd&asmda=asdakmsd"
# Note how the order has changed and the duplicate key has been removed due to
# Addressable's built-in normalisation.
"asdasda=asdaskdmasd&asmda=asdasmda&ACK=Success&asdmas=asdakmsd&asmda=adasda"[/ACK=([^&]*)&/]
$1 # => 'Success'
A quick approach:
s = "asdasda=asdaskdmasd&asmda=asdasmda&ACK=Success&asdmas=asdakmsd&asmda=adasda"
s.gsub(/ACK[=\w]+&/,"ACK[changedValue]&")
#=> asdasda=asdaskdmasd&asmda=asdasmda&ACK[changedValue]&asdmas=asdakmsd&asmda=adasda
s = "asdasda=asdaskdmasd&asmda=asdasmda&ACK=Success&asdmas=asdakmsd&asmda=adasda"
m = s.match /.*ACK=(.*?)&/
puts m[1]
and just for fun without regexp:
Hash[s.split("&").map{|p| p.split("=")}]["ACK"]

Resources