Class: URL

Inherits:
Object
  • Object
show all
Defined in:
lib/url.rb

Constant Summary collapse

Error =
Class.new(StandardError)
DOT =
"."
HTTP =
"http"
HTTPS =
"https"
NOTHING =
""
PORT_SEPARATOR =
":"
QUERY_STRING_SEPARATOR =
"?"
SEPARATOR =
"://"
SLASH =
"/"
SPACE =
" "

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(host:, path: nil, protocol: nil, port: nil, query: nil) ⇒ URL

Returns a new instance of URL.



115
116
117
118
119
120
121
# File 'lib/url.rb', line 115

def initialize(host:, path: nil, protocol: nil, port: nil, query: nil)
  @protocol = protocol
  @host = host
  @port = port&.to_i
  self.path = path
  @query = Rack::Utils.parse_nested_query(query)
end

Instance Attribute Details

#hostString

Parameters:

  • (String)

Returns:

  • (String)


32
33
34
# File 'lib/url.rb', line 32

def host
  @host
end

#pathObject

Returns the value of attribute path.



52
53
54
# File 'lib/url.rb', line 52

def path
  @path
end

#portObject

Parameters:

  • (String)


36
37
38
# File 'lib/url.rb', line 36

def port
  @port
end

#protocolString, HTTPS Also known as: scheme

Returns the protocol, defaults to “https”.

Returns:

  • (String, HTTPS)

    the protocol, defaults to “https”



168
169
170
# File 'lib/url.rb', line 168

def protocol
  @protocol || HTTPS
end

#queryHash

Returns:

  • (Hash)


40
41
42
# File 'lib/url.rb', line 40

def query
  @query
end

Class Method Details

.parse(string) ⇒ URL Also known as: []

Initializes a new URL object from a given string

Examples:

URL.parse("https://www.example.com:3000/path?query=string")
# => #<URL:0x00007f9b9c0b3b20 https://www.example.com:3000/path?query=string>

Parameters:

  • the (String)

    URL to parse

Returns:

  • (URL)

    A new URL object



61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/url.rb', line 61

def parse(string)
  string
    .to_str
    .dup
    .then { extract_protocol(_1) }
    .then { extract_host_and_port(*_1) }
    .then { extract_path_and_query(**_1) }
    .then do
      next nil if _1.compact.empty?

      new(**_1)
    end
end

Instance Method Details

#domainString

Returns the domain name

Examples:

url = URL.parse("https://www.example.com")
url.domain # => "example.com"

Returns:

  • (String)


215
216
217
# File 'lib/url.rb', line 215

def domain
  [sld, tld].compact.join(DOT)
end

#inspectObject



255
256
257
258
# File 'lib/url.rb', line 255

def inspect
  super.split(" ")[0].concat(" #{to_str}>")
  super.split(SPACE)[0].concat(" #{to_str}>")
end

#join(path) ⇒ URL #join(*paths) ⇒ URL

Adds a path to the URL

Examples:

url = URL.parse("https://www.example.com")
url.join("path").path("to", "nowhere")
url.to_s # => "https://www.example.com/path/to/nowhere"

Overloads:

  • #join(path) ⇒ URL

    Parameters:

    • path (String)

      a single string path

  • #join(*paths) ⇒ URL

    Parameters:

    • paths (Array<String>)

      an array of string paths

Returns:

  • (URL)

    self



144
145
146
147
148
149
150
151
152
# File 'lib/url.rb', line 144

def join(*paths)
  paths.map do |path|
    path.start_with?(SLASH) ? path.sub(SLASH, NOTHING) : path.dup
  end.then do |paths|
    self.path = Array(path).concat(paths).join(SLASH)
  end

  self
end

#merge(query) ⇒ URL

Append query parameters to the URL

Examples:

url = URL.parse("https://www.example.com")
url.merge(query: "string")
url.to_s # => "https://www.example.com?query=string"

Parameters:

  • (Hash)

Returns:

  • (URL)

    self



161
162
163
164
165
# File 'lib/url.rb', line 161

def merge(query)
  self.query = self.query.merge(deep_transform_keys(query))

  self
end

#sldString?

Returns the second level domain (SLD).

Returns:

  • (String, nil)

    the second level domain (SLD)



200
201
202
203
204
205
206
207
208
# File 'lib/url.rb', line 200

def sld
  domain_parts.then do |parts|
    if parts.size < 2
      parts.last
    else
      parts[-2]
    end
  end
end

#sld=(new_sld) ⇒ Object

Sets the second level domain (SLD)

Parameters:

  • (String)

Raises:

  • (URL::Error)

    if the host was initialized without a top level domain (TLD)



193
194
195
196
197
# File 'lib/url.rb', line 193

def sld=(new_sld)
  domain_parts.tap do |parts|
    @host = [subdomain, new_sld, tld].compact.join(DOT)
  end
end

#subdomainString?

Returns the subdomain

Returns:

  • (String, nil)


232
233
234
235
236
237
238
# File 'lib/url.rb', line 232

def subdomain
  (domain_parts - [sld, tld].compact).then do |parts|
    next if parts.empty?

    parts.join(DOT)
  end
end

#subdomain=(new_subdomain) ⇒ String

Parameters:

  • (String)

Returns:

  • (String)

Raises:

  • (URL::Error)

    if the host was initialized without a top level domain (TLD)



222
223
224
225
226
227
228
# File 'lib/url.rb', line 222

def subdomain=(new_subdomain)
  domain_parts.tap do |parts|
    raise(Error, ERROR_MESSAGES[:subdomain=][:missing_tld] % {url: to_s}) if tld.nil?

    @host = [new_subdomain, sld, tld].join(DOT)
  end
end

#tldString?

Returns the top level domain (TLD)

Returns:

  • (String, nil)


186
187
188
# File 'lib/url.rb', line 186

def tld
  domain_parts.last if domain_parts.size > 1
end

#tld=(new_tld) ⇒ Object

Sets the top level domain (TLD)

Parameters:

  • (String)

Raises:

  • (URL::Error)

    if the host was initialized without a top level domain (TLD)



176
177
178
179
180
181
182
# File 'lib/url.rb', line 176

def tld=(new_tld)
  domain_parts.tap do |parts|
    raise(Error, ERROR_MESSAGES[:tld=][:missing_tld] % {url: to_s}) if tld.nil?

    @host = [subdomain, sld, new_tld].compact.join(DOT)
  end
end

#to_strString Also known as: to_s

Returns the full URL as a string

Returns:

  • (String)


242
243
244
245
246
247
248
249
250
251
# File 'lib/url.rb', line 242

def to_str
  [
    protocol,
    SEPARATOR,
    host,
    port_str,
    path_str,
    query_params
  ].compact.join
end