ruby - delete from a string - ruby

I have the following strings:
src = "dav://w.lvh.me:3000/Home/Transit/file"
host = "w.lvh.me:3000"
What I want to obtain is "/Home/Transit/file" using those two strings
I thought of searching for host in src and delete it the first time it appears, and everything before it, but I'm not sure exactly how to do that. Or maybe there's a better way?
Any help would be appreciated!

There is a better way indeed:
require 'uri'
src = "dav://w.lvh.me:3000/Home/Transit/file"
src = URI.parse src
src.path # => "/Home/Transit/file"
When there are spaces in the string, you must pass extra step of escaping/unescaping. Fortunantly, this is simple:
require 'uri'
src = "dav://w.lvh.me:3000/Home/Transit/Folder 144/webdav_put_request"
src = URI.parse(URL.escape src)
URL.unescape(src.path) # => "/Home/Transit/Folder 144/webdav_put_request"

This should do the job:
src = "dav://w.lvh.me:3000/Home/Transit/file"
host = "w.lvh.me:3000"
result = src.sub(/.*#{host}/, '')
#=> "/Home/Transit/file"

Related

Can't 'file.open.read' a url within a ruby if-block

I want to create a ruby script which will take barcodes from a text file, search a webservice for that barcode and download the result.
First I tried to test the webservice download. In a file when I hardcode the query things work fine:
result_download = open('http://webservice.org/api/?query=barcode:78686112327', 'User-Agent' => 'UserAgent email#gmail.com').read
It all works fine.
When I try to take the barcode from a textfile and run the query I run into problems.
IO.foreach(filename) {|barcode| barcode
website = "'http://webservice.org/api/?query=barcode:"+barcode.to_str.chomp + "', 'User-Agent' => 'UserAgent email#gmail.com'"
website = website.to_s
mb_metadata = open(website).read
}
The result of this is:
/home/user/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/open-uri.rb:37:in `initialize': No such file or directory # rb_sysopen - http://webservice.org/api/?query=barcode:78686112327', 'User-Agent' => 'UserAgent email#gmail.com' (Errno::ENOENT)
I can't figure out if this problem occurs because the string I generate somehow isn't a valid url and ruby is trying to open a non-existent file, or is the issue that I am doing all this in a for loop and the file/url doesn't exist there. I have tried using open(website).write instead of open(website).read but that produces the same error.
Any help would be much appreciated.
The error message you get explicitly states, that there is no such file:
http://webservice.org/api/?query=barcode:78686112327', 'User-Agent' => 'UserAgent email#gmail.com'.
You try to pass all the parameters to open method using 1 big string (website), which is wrong. You should do it like that.
IO.foreach(filename) do |barcode|
website = "http://webservice.org/api/?query=barcode:#{barcode.to_str.chomp}"
mb_metadata = open(website, 'User-Agent' => 'UserAgent email#gmail.com').read
end

Create a image file from binary data in Ruby

I am able to access the binary data of a file and store it in a varible like this
s = File.binread("sample_22122015_03.jpg")
bits = s.unpack("B*")[0]
where bits has data like this "101001001010100100......."
However, I want to do some changes and again write the binary data back to a new image, but I am unable to.
I am using
File.open('shipping_label_new.jpg', 'wb') do|f|
f.write(Base64.decode64(bits))
end
but it's not working and I see that the image is corrupt.
Try this code
s = File.binread("test_img.jpg")
bits = s.unpack("B*")
File.open('new_test_img.jpg', 'wb') do|f|
f.write(bits.pack("B*"))
end
The reverse of String.unpack is Array.pack:
:007 > bits = 'abc'.unpack("B*")
=> ["011000010110001001100011"]
:008 > bits.pack("B*")
=> "abc"

Ruby URI - How to get entire path after URL

How do you get the full path of the URL given the following
uri = URI("http://foo.com/posts?id=30&limit=5#time=1305298413")
I just want posts?id=30&limit=5#time=1305298413
I tried uri.path and that returns /posts and ui.query returns 'id=30&limit=5'
The method you are looking for is request_uri
uri.request_uri
=> "/posts?id=30&limit=5"
You can use any method you'd like to remove the leading / if needed.
Edit: To get the part after the # sign, use fragment:
[uri.request_uri, uri.fragment].join("#")
=> "/posts?id=30&limit=5#time=1305298413"
You can ask the URI object for its path, query, and fragment like this:
"#{uri.path}?#{uri.query}##{uri.fragment}"
# => "/posts?id=30&limit=5#time=1305298413"
or (a little more consice, but less explicit):
"#{uri.request_uri}##{uri.fragment}"
# => "/posts?id=30&limit=5#time=1305298413"
A bit of an artsy solution, for completeness – others may be more reasonable :)
uri.dup.tap { _1.scheme = _1.user = _1.password = _1.host = _1.port = nil }.to_s
Though a benefit of this solution is that it also handles URI::Generic like you'd get from parsing a standalone path:
uri = URI.parse("/foo?bar#baz") # => #<URI::Generic /foo?bar#baz>
Solutions that rely on URI::HTTP#request_uri won't work with URI::Generic. So if you're writing code that accepts both full URLs and paths, that may be a factor.
File.basename("http://foo.com/posts?id=30&limit=5#time=1305298413")
# => "posts?id=30&limit=5#time=1305298413"

Making a URL in a string usable by Ruby's Net::HTTP

Ruby's Net:HTTP needs to be given a full URL in order for it to connect to the server and get the file properly. By "full URL" I mean a URL including the http:// part and the trailing slash if it needs it. For instance, Net:HTTP won't connect to a URL looking like this: example.com, but will connect just fine to http://example.com/. Is there any way to make sure a URL is a full URL, and add the required parts if it isn't?
EDIT: Here is the code I am using:
parsed_url = URI.parse(url)
req = Net::HTTP::Get.new(parsed_url.path)
res = Net::HTTP.start(parsed_url.host, parsed_url.port) {|http|
http.request(req)
}
If this is only doing what the sample code shows, Open-URI would be an easier approach.
require 'open-uri'
res = open(url).read
This would do a simple check for http/https:
if !(url =~ /^https?:/i)
url = "http://" + url
end
This could be a more general one to handle multiple protocols (ftp, etc.)
if !(url =~ /^\w:/i)
url = "http://" + url
end
In order to make sure parsed_url.path gives you a proper value (it should be / when no specific path was provided), you could do something like this:
req = Net::HTTP::Get.new(parsed_url.path.empty? ? '/' : parsed_url.path)

How to create a link in Sinatra that points to a directory of files?

I have an application that calls an other application that populates a directory. Once it is finished I want to provide a link to the directory that contains the created files and people can examine or download them via the browser:
For example this works to provide a link to a single file: (Note this uses HAML) but the idea is the same
%p
- output_href = File.join("..","..","test_runs",File.basename(#dealclick_test_run.result_filename) )
Result file =
%a{:id => "result-file", :href => "#{output_href}"}
= File.basename(#dealclick_test_run.result_filename)`
The corresponding code for the directory doesn't work:
%p
Results:
- output_href = File.join("..","..","test_runs",File.basename(#dp_test_run.result_filename) )
%a( id = "dealprocessor_results" href = "#{output_href}" )
= File.basename(#dp_test_run.result_filename)
What am I doing wrong?
%a( id = "dealprocessor_results" href = "#{output_href}" )
should be
%a(:id = "dealprocessor_results" :href = "#{output_href}" )

Resources