module Furi
Constants
- ALIASES
- COMBINED_PARTS
- DELEGATES
- ESSENTIAL_PARTS
- PARTS
- PROTOCOLS
- ROOT
- SSL_MAPPING
- VERSION
- WEB_PROTOCOL
Public Class Methods
build(argument)
click to toggle source
Builds an URL from given parts
Furi.build(path: "/dashboard", host: 'example.com', protocol: "https") # => "https://example.com/dashboard"
# File lib/furi.rb, line 73 def self.build(argument) Uri.new(argument).to_s end
defaults(string, parts)
click to toggle source
Puts the default values for given URL that are not defined
Furi.defaults("gusiev.com/hello.html", protocol: 'http', path: '/index.html') # => "http://gusiev.com/hello.html"
# File lib/furi.rb, line 100 def self.defaults(string, parts) parse(string).defaults(parts).to_s end
join(*uris)
click to toggle source
# File lib/furi.rb, line 172 def self.join(*uris) uris.map do |uri| Furi.parse(uri) end.reduce do |memo, uri| memo.send(:join, uri) end end
parse(argument, parts = nil)
click to toggle source
Parses a given string and return an URL object Optionally accepts parts to update the parsed URL object
# File lib/furi.rb, line 65 def self.parse(argument, parts = nil) Uri.new(argument).update(parts) end
parse_query(query)
click to toggle source
Parses a query into nested paramters hash using a rack convension with square brackets.
Furi.parse_query("a[]=1&a[]=2") # => {a: [1,2]} Furi.parse_query("p[email]=a&a[two]=2") # => {a: {one: 1, two: 2}} Furi.parse_query("p[one]=1&a[two]=2") # => {a: {one: 1, two: 2}} Furi.serialize({p: {name: 'Bogdan Gusiev', email: 'bogdan@example.com', data: {one: 1, two: 2}}}) # => "p%5Bname%5D=Bogdan&p%5Bemail%5D=bogdan%40example.com&p%5Bdata%5D%5Bone%5D=1&p%5Bdata%5D%5Btwo%5D=2"
# File lib/furi.rb, line 124 def self.parse_query(query) return Furi::Utils.stringify_keys(query) if query.is_a?(Hash) params = {} query_tokens(query).each do |token| parse_query_token(params, token.name, token.value) end return params end
query_tokens(query)
click to toggle source
Parses query key/value pairs from query string and returns them raw without organising them into hashes and without normalising them.
Furi.query_tokens("a=1&b=2").map {|k,v| "#{k} -> #{v}"} # => ['a -> 1', 'b -> 2'] Furi.query_tokens("a=1&a=1&a=2").map {|k,v| "#{k} -> #{v}"} # => ['a -> 1', 'a -> 1', 'a -> 2'] Furi.query_tokens("name=Bogdan&email=bogdan%40example.com") # => [name=Bogdan, email=bogdan@example.com] Furi.query_tokens("a[one]=1&a[two]=2") # => [a[one]=1, a[two]=2]
# File lib/furi.rb, line 142 def self.query_tokens(query) case query when Enumerable, Enumerator query.map do |token| QueryToken.parse(token) end when nil, '' [] when String query.gsub(/\A\?/, '').split(/[&;] */n, -1).map do |p| QueryToken.parse(p) end else raise QueryParseError, "can not parse #{query.inspect} query tokens" end end
replace(string, parts)
click to toggle source
Replaces a given URL string with given parts. Same as update but works different for URL query parameter: replaces newly specified parameters instead of merging to existing ones
Furi.update("/hello.html?a=1", host: 'gusiev.com', query: {b: 2}) # => "gusiev.com/hello.html?a=1&b=2"
# File lib/furi.rb, line 111 def self.replace(string, parts) parse(string).replace(parts).to_s end
serialize(query, namespace = nil)
click to toggle source
Serializes query parameters into query string. Optionaly accepts a basic name space.
Furi.serialize({a: 1, b: 2}) # => "a=1&b=2" Furi.serialize({a: [1,2]}) # => "a[]=1&a[]=2" Furi.serialize({a: {b: 1, c:2}}) # => "a[b]=1&a[c]=2" Furi.serialize({name: 'Bogdan', email: 'bogdan@example.com'}, "person") # => "person[name]=Bogdan&person[email]=bogdan%40example.com"
# File lib/furi.rb, line 168 def self.serialize(query, namespace = nil) serialize_tokens(query, namespace).join("&") end
update(string, parts)
click to toggle source
Replaces a given URL string with given parts
Furi.update("http://gusiev.com", protocol: 'https', subdomain: 'www') # => "https://www.gusiev.com"
# File lib/furi.rb, line 89 def self.update(string, parts) parse(string).update(parts).to_s end
Also aliased as: merge
Protected Class Methods
parse_query_token(params, name, value)
click to toggle source
# File lib/furi.rb, line 228 def self.parse_query_token(params, name, value) name =~ %r(\A[\[\]]*([^\[\]]+)\]*) namespace = $1 || '' after = $' || '' return if namespace.empty? current = params[namespace] if after == "" current = value elsif after == "[]" current ||= [] unless current.is_a?(Array) raise QueryParseError, "expected Array (got #{current.class}) for param `#{namespace}'" end current << value elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$) child_key = $1 current ||= [] unless current.is_a?(Array) raise QueryParseError, "expected Array (got #{current.class}) for param `#{namespace}'" end if current.last.is_a?(Hash) && !current.last.key?(child_key) parse_query_token(current.last, child_key, value) else current << parse_query_token({}, child_key, value) end else current ||= {} unless current.is_a?(Hash) raise QueryParseError, "expected Hash (got #{current.class}) for param `#{namespace}'" end current = parse_query_token(current, after, value) end params[namespace] = current return params end
serialize_tokens(query, namespace = nil)
click to toggle source
# File lib/furi.rb, line 194 def self.serialize_tokens(query, namespace = nil) case query when Hash result = query.map do |key, value| unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty? serialize_tokens(value, namespace ? "#{namespace}[#{key}]" : key) else nil end end result.flatten! result.compact! result when Array if namespace.nil? || namespace.empty? raise FormattingError, "Can not serialize Array without namespace" end namespace = "#{namespace}[]" query.map do |item| if item.is_a?(Array) raise FormattingError, "Can not serialize #{item.inspect} as element of an Array" end serialize_tokens(item, namespace) end else if namespace QueryToken.new(namespace, query) else [] end end end