require 'json'
module Ajax
module Helpers
module RequestHelper
# Recursive merge values
DEEP_MERGE = lambda do |key, v1, v2|
if v1.is_a?(Hash) && v2.is_a?(Hash)
v1.merge(v2, &DEEP_MERGE)
elsif v1.is_a?(Array) && v2.is_a?(Array)
v1.concat(v2)
else
[v1, v2].compact.first
end
end
# Set the value at key in the Ajax-Info header
# in object.
#
# object can be a Hash or instance of ActionController::Request
# key Symbol or String hash key, converted to String
# value any value that con be converted to JSON
#
# All Hash and Array values are deep-merged.
# Hash keys are converted to Strings.
def set_header(object, key, value)
headers = object.is_a?(::ActionController::Response) ? object.headers : object
key = key.to_s
info = case headers["Ajax-Info"]
when String
JSON.parse(headers["Ajax-Info"]) rescue {}
when Hash
headers["Ajax-Info"]
else
{}
end
# Deep merge hashes
if info.has_key?(key) &&
value.is_a?(Hash) &&
info[key].is_a?(Hash)
value = value.stringify_keys!
value = info[key].merge(value, &DEEP_MERGE)
end
# Concat arrays
if info.has_key?(key) &&
value.is_a?(Array) &&
info[key].is_a?(Array)
value = info[key].concat(value)
end
info[key] = value
headers["Ajax-Info"] = info.to_json
end
# Return the value at key key from the Ajax-Info header
# in object.
#
# object can be a Hash or instance of ActionController::Request
# key Symbol or String hash key, converted to String
def get_header(object, key)
headers = object.is_a?(::ActionController::Request) ? object.headers : object
key = key.to_s
info = case headers["Ajax-Info"]
when String
JSON.parse(headers["Ajax-Info"]) rescue {}
when Hash
headers["Ajax-Info"]
else
{}
end
info[key]
end
# Set one or more paths that can be accessed directly without the AJAX framework.
#
# Useful for excluding pages with HTTPS content on them from being loaded
# via AJAX.
#
# paths a list of String or Regexp instances that are matched
# against each REQUEST_PATH.
#
# The string and regex paths are modified to match full URLs by prepending
# them with the appropriate regular expression.
def exclude_paths(paths=nil, expand = true)
if !instance_variable_defined?(:@exclude_paths)
@exclude_paths = []
end
(paths || []).each do |path|
if expand
@exclude_paths << /^(\w+\:\/\/[^\/]+\/?)?#{path.to_s}$/
else
@exclude_paths << path
end
end
@exclude_paths
end
# Directly set regexes for one or more paths that can be accessed directly without the AJAX framework.
def exclude_regex(exclude_regex=nil)
exclude_paths(exclude_regex, false)
end
# Return a boolean indicating whether or not to exclude a path from the
# AJAX redirect.
def exclude_path?(path)
!!((@exclude_paths || []).find do |excluded|
!!excluded.match(path)
end)
end
end
end
end