lib/crepe/util.rb
require 'rack/mime'
module Crepe
# A collection of helper methods Crepe uses internally.
module Util
module_function
# Recursively dups hashes and arrays.
#
# @param [Hash, Array, Object] value the object to recursively dup
# @return [Hash, Array, Object] a duplicate hash or array (with any nested
# hashes or arrays duplicated, as well), or the original object
def deep_collection_dup value
case value
when Hash
value.each_with_object value.dup do |(k, v), h|
h[deep_collection_dup k] = deep_collection_dup v
end
when Array then value.map { |v| deep_collection_dup v }
else value
end
end
# Recursively merges one hash with another, merging any nested hash value.
#
# @param [Hash] hash the hash whose values take less precedence
# @param [Hash] other_hash the hash whose values take greater precedence
# @return [Hash] a new, merged hash
# @see #deep_merge!
def deep_merge hash, other_hash
deep_merge! deep_collection_dup(hash), other_hash
end
# Recursively merges one hash in place with another, merging any nested
# hash value.
#
# @param [Hash] hash the hash whose values take less precedence
# @param [Hash] other_hash the hash whose values take greater precedence
# @return [Hash] the original hash, merged
# @see #deep_merge
def deep_merge! hash, other_hash
other_hash.each do |key, value|
if hash[key].is_a?(Hash) && value.is_a?(Hash)
hash[key] = deep_merge hash[key], value
else
hash[key] = value
end
end
hash
end
# Normalizes a given path by inserting a leading slash if none exists, and
# deleting repeating and trailing slashes.
#
# Util.normalize_path! 'the//road/less/traveled/by/'
# # => "/the/road/less/traveled/by"
#
# @param [String] path a path to be normalized
# @return [String] a normalized path
# @see #normalize_path!
def normalize_path path
normalize_path! path.dup
end
# Normalizes a given path in place by inserting a leading slash if none
# exists, and deleting repeating and trailing slashes.
#
# path = 'the//road/less/traveled/by/'
# Util.normalize_path! path
# path
# # => "/the/road/less/traveled/by"
#
# @param [String] path a path to be normalized
# @return [String] the original path, normalized
# @see #normalize_path
def normalize_path! path
path.squeeze! '/'
path.chomp! '/'
path.prepend '/' unless path.start_with? '/'
path
end
# Returns an array of media types for a given array of formats.
#
# @param [Array<Symbol, String>] formats a list of formats
# @return [Array<String>] a list of media types
# @see #media_type
def media_types formats
formats.map(&method(:media_type))
end
# Returns the media type for a given format.
#
# Util.media_type :json # => "application/json"
#
# @param [Symbol, String] format a format
# @return [String] a media type
# @see #media_types
def media_type format
Rack::Mime.mime_type ".#{format}", format
end
end
end