Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

create an URL using host and multiple path strings in Rails

I'd like to create an URL using an endpoint and a path or a host and path. Unfortunately URI.join doesn't allow to do it:

pry(main)> URI.join "https://service.com", "endpoint",  "/path"
=> #<URI::HTTPS:0xa947f14 URL:https://service.com/path>
pry(main)> URI.join "https://service.com/endpoint",  "/path"
=> #<URI::HTTPS:0xabba56c URL:https://service.com/path>

and what I want is: "https://service.com/endpoint/path". How could I do it in Ruby/Rails?

EDIT: As the URI.join has some drawback, I'm tempted to use File.join:

URI.join("https://service.com", File.join("endpoint",  "/path"))

What do you think?

like image 310
mrzasa Avatar asked Feb 26 '13 13:02

mrzasa


2 Answers

URI.join works like what you'd expect an <a> tag to work.

You're joining example.com, endpoint, /path, so /path takes you back to the root of the domain, instead of appending it.

You need to end the endpoint with a /, and not start the path with /.

URI.join "https://service.com/", "endpoint/",  "path"
=> #<URI::HTTPS:0x007f8a5b0736d0 URL:https://service.com/endpoint/path>

Edit: As per your request in the comment below, try this:

def join(*args)
  args.map { |arg| arg.gsub(%r{^/*(.*?)/*$}, '\1') }.join("/")
end

Test:

> join "https://service.com/", "endpoint", "path"
=> "https://service.com/endpoint/path"
> join "http://example.com//////", "///////a/////////", "b", "c"
=> "http://example.com/a/b/c"
like image 166
Dogbert Avatar answered Sep 25 '22 03:09

Dogbert


Looks like URI.join checks for the presence of slash character '/' to figures out the folder in the url path. So, if you missed the trailing slash '/' in the path it will not treat it as folder, and omit it. Check this out:

URI.join("https://service.com", 'omitted_part', 'omitted_again', 'end_point_stays').to_s
# =>"https://service.com/end_point_stays"

Here, if we try to JOIN THE WORDS ONLY, first and last params only stay, rest are omitted, where first param is, absolute uri with protocol & last param is, the end point.

So, if you want to include the folder component, add trailing slash in each folder-component, then only it is considered part of the path:

URI.join("https://service.com", 'omitted_no_trailing_slash', 'omitted_again', 'stays/', 'end_point_stays').to_s
# => "https://service.com/stays/end_point_stays"

One more interesting thing to consider is that, if you are providing path in first parameter it acts as follows:

URI.join("https://service.com/omitted_because_no_trailing_slash", 'end_point_stays').to_s
# => "https://service.com/end_point_stays"
URI.join("https://service.com/stays_because_of_trailing_slash/", 'end_point_stays').to_s
# => "https://service.com/stays_because_of_trailing_slash/end_point_stays"
URI.join("https://service.com/safe_with_trailing_slash/omitted_because_no_trailing_slash", 'end_point_stays').to_s
# => "https://service.com/safe_with_trailing_slash/end_point_stays"
like image 20
thegauraw Avatar answered Sep 22 '22 03:09

thegauraw