ajax 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +291 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/app/controllers/ajax_controller.rb +3 -0
- data/app/views/ajax/framework.html.erb +7 -0
- data/config/initializers/ajax.rb +14 -0
- data/lib/ajax.rb +79 -0
- data/lib/ajax/action_controller.rb +154 -0
- data/lib/ajax/action_view.rb +56 -0
- data/lib/ajax/helpers.rb +15 -0
- data/lib/ajax/helpers/request_helper.rb +76 -0
- data/lib/ajax/helpers/robot_helper.rb +31 -0
- data/lib/ajax/helpers/url_helper.rb +47 -0
- data/lib/ajax/railtie.rb +7 -0
- data/lib/ajax/routes.rb +12 -0
- data/lib/ajax/spec/extension.rb +34 -0
- data/lib/ajax/spec/helpers.rb +95 -0
- data/lib/ajax/tasks.rb +1 -0
- data/lib/rack-ajax.rb +60 -0
- data/lib/rack-ajax/decision_tree.rb +60 -0
- data/lib/rack-ajax/parser.rb +115 -0
- data/public/images/loading-icon-large.gif +0 -0
- data/public/images/loading-icon-small.gif +0 -0
- data/public/javascripts/ajax.js +529 -0
- data/public/javascripts/jquery.address-1.1.js +450 -0
- data/public/javascripts/jquery.address-1.1.min.js +11 -0
- data/public/javascripts/jquery.address-1.2.js +528 -0
- data/public/javascripts/jquery.address-1.2.min.js +25 -0
- data/public/javascripts/jquery.address-1.2rc.js +599 -0
- data/public/javascripts/jquery.address-1.2rc.min.js +27 -0
- data/public/javascripts/jquery.json-2.2.js +178 -0
- data/public/javascripts/jquery.json-2.2.min.js +31 -0
- data/rails/init.rb +4 -0
- data/rails/install.rb +23 -0
- data/rails/uninstall.rb +1 -0
- data/spec/ajax/helpers_spec.rb +102 -0
- data/spec/ajax/request_helper_spec.rb +33 -0
- data/spec/integration/ajax_spec.rb +146 -0
- data/spec/rack-ajax/parser_spec.rb +62 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +18 -0
- data/tasks/ajax_tasks.rake +15 -0
- metadata +106 -0
@@ -0,0 +1,154 @@
|
|
1
|
+
module Ajax
|
2
|
+
module ActionController
|
3
|
+
def self.included(klass)
|
4
|
+
klass.class_eval do
|
5
|
+
alias_method_chain :render, :ajax
|
6
|
+
alias_method_chain :redirect_to_full_url, :ajax
|
7
|
+
|
8
|
+
append_after_filter :process_response_headers
|
9
|
+
end
|
10
|
+
klass.extend(ClassMethods)
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
|
15
|
+
# Set a custom response header if the request is AJAX.
|
16
|
+
#
|
17
|
+
# Call with <tt>key</tt> and optional <tt>value</tt>. Pass a
|
18
|
+
# block to yield a dynamic value.
|
19
|
+
#
|
20
|
+
# Accepts :only and :except conditions because we create
|
21
|
+
# an after_filter.
|
22
|
+
def ajax_header(*args, &block)
|
23
|
+
return unless Ajax.is_enabled?
|
24
|
+
|
25
|
+
options = args.extract_options!
|
26
|
+
key, value = args.shift, args.shift
|
27
|
+
value = block_given? ? Proc.new : value
|
28
|
+
|
29
|
+
prepend_after_filter(options) do |controller|
|
30
|
+
if controller.request.xhr?
|
31
|
+
value = value.is_a?(Proc) ? controller.instance_eval(&value) : value
|
32
|
+
Ajax.set_header(controller.response, key, value)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Set the layout to use for AJAX requests.
|
38
|
+
#
|
39
|
+
# By default we look in layouts/ajax/ for this controllers default
|
40
|
+
# layout and render that. If it can't be found, the default layout
|
41
|
+
# is used.
|
42
|
+
def ajax_layout(template_name)
|
43
|
+
write_inheritable_attribute(:ajax_layout, template_name)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
# Redirect to hashed URLs unless the path is excepted.
|
50
|
+
#
|
51
|
+
# Store the URL that we are redirecting to in the session.
|
52
|
+
# If we then have a request for the root URL we know
|
53
|
+
# to render this URL into it.
|
54
|
+
#
|
55
|
+
# If redirecting back to the referer, use the referer
|
56
|
+
# in the Ajax-Info header because it includes the
|
57
|
+
# hashed part of the URL. Otherwise the referer is
|
58
|
+
# always the root url.
|
59
|
+
#
|
60
|
+
# For AJAX requests, respond with an AJAX-suitable
|
61
|
+
# redirect.
|
62
|
+
def redirect_to_full_url_with_ajax(url, status)
|
63
|
+
return redirect_to_full_url_without_ajax(url, status) unless Ajax.is_enabled?
|
64
|
+
raise DoubleRenderError if performed?
|
65
|
+
|
66
|
+
if url == request.headers["Referer"] && !request.headers['Ajax-Info'].blank?
|
67
|
+
url = request.headers['Ajax-Info']['referer']
|
68
|
+
Ajax.logger.debug("[ajax] using referer #{url} from Ajax-Info")
|
69
|
+
end
|
70
|
+
|
71
|
+
if !Ajax.exclude_path?(url) && !Ajax.is_hashed_url?(url)
|
72
|
+
url = Ajax.hashed_url_from_traditional(url)
|
73
|
+
Ajax.logger.info("[ajax] rewrote redirect to #{url}")
|
74
|
+
end
|
75
|
+
|
76
|
+
session[:redirected_to] = url
|
77
|
+
if request.xhr?
|
78
|
+
render(:update) { |page| page.redirect_to(url) }
|
79
|
+
else
|
80
|
+
redirect_to_full_url_without_ajax(url, status)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Convert the Ajax-Info hash to JSON before the request is sent.
|
85
|
+
def process_response_headers
|
86
|
+
case response.headers['Ajax-Info']
|
87
|
+
when Hash
|
88
|
+
response.headers['Ajax-Info'] = response.headers['Ajax-Info'].to_json
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# Intercept rendering to customize the headers and layout handling
|
94
|
+
#
|
95
|
+
def render_with_ajax(options = nil, extra_options = {}, &block)
|
96
|
+
return render_without_ajax(options, extra_options, &block) unless Ajax.is_enabled?
|
97
|
+
|
98
|
+
original_args = [options, extra_options]
|
99
|
+
if request.xhr?
|
100
|
+
|
101
|
+
# Options processing taken from ActionController::Base#render
|
102
|
+
if options.nil?
|
103
|
+
options = { :template => default_template, :layout => true }
|
104
|
+
elsif options == :update
|
105
|
+
options = extra_options.merge({ :update => true })
|
106
|
+
elsif options.is_a?(String) || options.is_a?(Symbol)
|
107
|
+
case options.to_s.index('/')
|
108
|
+
when 0
|
109
|
+
extra_options[:file] = options
|
110
|
+
when nil
|
111
|
+
extra_options[:action] = options
|
112
|
+
else
|
113
|
+
extra_options[:template] = options
|
114
|
+
end
|
115
|
+
options = extra_options
|
116
|
+
elsif !options.is_a?(Hash)
|
117
|
+
extra_options[:partial] = options
|
118
|
+
options = extra_options
|
119
|
+
end
|
120
|
+
|
121
|
+
default = pick_layout(options)
|
122
|
+
default = default.path_without_format_and_extension unless default.nil?
|
123
|
+
ajax_layout = layout_for_ajax(default)
|
124
|
+
ajax_layout = ajax_layout.path_without_format_and_extension unless ajax_layout.nil?
|
125
|
+
options[:layout] = ajax_layout unless ajax_layout.nil?
|
126
|
+
|
127
|
+
# Send the current layout and controller in a custom response header
|
128
|
+
Ajax.set_header(response, :layout, ajax_layout)
|
129
|
+
Ajax.set_header(response, :controller, self.class.controller_name)
|
130
|
+
end
|
131
|
+
render_without_ajax(options, extra_options, &block)
|
132
|
+
end
|
133
|
+
|
134
|
+
# Return the layout to use for an AJAX request, or the default layout if one
|
135
|
+
# cannot be found. If no default is known, <tt>layouts/ajax/application</tt> is used.
|
136
|
+
#
|
137
|
+
# If no ajax_layout is set, look for the default layout in <tt>layouts/ajax</tt>.
|
138
|
+
# If the layout cannot be found, use the default.
|
139
|
+
#
|
140
|
+
# FIXME: Use hard-coded html layout extension because <tt>default_template_format</tt>
|
141
|
+
# is sometimes :js which means the layout isn't found.
|
142
|
+
def layout_for_ajax(default) #:nodoc:
|
143
|
+
ajax_layout = self.class.read_inheritable_attribute(:ajax_layout)
|
144
|
+
if ajax_layout.nil? || !(ajax_layout =~ /^layouts\/ajax/)
|
145
|
+
find_layout("layouts/ajax/#{default.sub(/layouts(\/)?/, '')}", 'html') unless default.nil?
|
146
|
+
else
|
147
|
+
ajax_layout
|
148
|
+
end
|
149
|
+
rescue ::ActionView::MissingTemplate
|
150
|
+
Ajax.logger.info("[ajax] no layout found in layouts/ajax using #{default}")
|
151
|
+
default
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Ajax
|
2
|
+
module ActionView
|
3
|
+
def self.included(klass)
|
4
|
+
klass.class_eval do
|
5
|
+
alias_method_chain :link_to, :ajax if method_defined?(:link_to)
|
6
|
+
end
|
7
|
+
klass.send(:include, Helpers)
|
8
|
+
end
|
9
|
+
|
10
|
+
module Helpers
|
11
|
+
|
12
|
+
# Set a custom response header if the request is AJAX.
|
13
|
+
def ajax_header(key, value)
|
14
|
+
return unless Ajax.is_enabled? && request.xhr?
|
15
|
+
Ajax.set_header(response, key, value)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
# Include an attribute on all outgoing links to mark them as Ajax deep links.
|
22
|
+
#
|
23
|
+
# The deep link will be the path and query string from the href.
|
24
|
+
#
|
25
|
+
# To specify a different deep link pass <tt>:data-deep-link => '/deep/link/path'</tt>
|
26
|
+
# in the <tt>link_to</tt> <tt>html_options</tt>.
|
27
|
+
#
|
28
|
+
# To turn off deep linking for a URL, pass <tt>:traditional => true</tt> or
|
29
|
+
# <tt>:data-deep-link => nil</tt>.
|
30
|
+
#
|
31
|
+
# Any paths matching the paths in Ajax.exclude_paths will automatically be
|
32
|
+
# linked to traditionally.
|
33
|
+
def link_to_with_ajax(*args, &block)
|
34
|
+
if Ajax.is_enabled? && !block_given?
|
35
|
+
options = args.second || {}
|
36
|
+
html_options = args.third
|
37
|
+
html_options = (html_options || {}).stringify_keys
|
38
|
+
|
39
|
+
# Insert the deep link unless the URL is traditional
|
40
|
+
if !html_options.has_key?('data-deep-link') && !html_options.delete('traditional')
|
41
|
+
path = url_for(options)
|
42
|
+
|
43
|
+
# Is this path to be excluded?
|
44
|
+
unless Ajax.exclude_path?(path)
|
45
|
+
if path.match(%r[^(http:\/\/[^\/]*)(\/?.*)])
|
46
|
+
path = $2
|
47
|
+
end
|
48
|
+
html_options['data-deep-link'] = path
|
49
|
+
end
|
50
|
+
end
|
51
|
+
args[2] = html_options
|
52
|
+
end
|
53
|
+
link_to_without_ajax(*args, &block)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/ajax/helpers.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'ajax/helpers/request_helper'
|
2
|
+
require 'ajax/helpers/robot_helper'
|
3
|
+
require 'ajax/helpers/url_helper'
|
4
|
+
|
5
|
+
module Ajax #:nodoc:
|
6
|
+
module Helpers #:nodoc:
|
7
|
+
def self.included(klass)
|
8
|
+
klass.class_eval do
|
9
|
+
extend RequestHelper
|
10
|
+
extend RobotHelper
|
11
|
+
extend UrlHelper
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Ajax
|
2
|
+
module Helpers
|
3
|
+
module RequestHelper
|
4
|
+
# Recursive merge values
|
5
|
+
DEEP_MERGE = lambda do |key, v1, v2|
|
6
|
+
if v1.is_a?(Hash) && v2.is_a?(Hash)
|
7
|
+
v1.merge(v2, &DEEP_MERGE)
|
8
|
+
elsif v1.is_a?(Array) && v2.is_a?(Array)
|
9
|
+
v1.concat(v2)
|
10
|
+
else
|
11
|
+
[v1, v2].compact.first
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Hash and/or Array values are merged so you can set multiple values
|
16
|
+
def set_header(object, key, value)
|
17
|
+
headers = object.is_a?(::ActionController::Response) ? object.headers : object
|
18
|
+
unless headers["Ajax-Info"].is_a?(Hash)
|
19
|
+
headers["Ajax-Info"] = {}
|
20
|
+
end
|
21
|
+
|
22
|
+
# Deep merge hashes
|
23
|
+
if headers["Ajax-Info"].has_key?(key.to_s) &&
|
24
|
+
value.is_a?(Hash) &&
|
25
|
+
headers["Ajax-Info"][key.to_s].is_a?(Hash)
|
26
|
+
value = headers["Ajax-Info"][key.to_s].merge(value, &DEEP_MERGE)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Concat arrays
|
30
|
+
if headers["Ajax-Info"].has_key?(key.to_s) &&
|
31
|
+
value.is_a?(Array) &&
|
32
|
+
headers["Ajax-Info"][key.to_s].is_a?(Array)
|
33
|
+
value = headers["Ajax-Info"][key.to_s].concat(value)
|
34
|
+
end
|
35
|
+
|
36
|
+
headers["Ajax-Info"][key.to_s] = value
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_header(object, key)
|
40
|
+
headers = object.is_a?(::ActionController::Request) ? object.headers : object
|
41
|
+
unless headers["Ajax-Info"].is_a?(Hash)
|
42
|
+
headers["Ajax-Info"] = {}
|
43
|
+
end
|
44
|
+
headers['Ajax-Info'][key.to_s]
|
45
|
+
end
|
46
|
+
|
47
|
+
# Set one or more paths that can be accessed directly without the AJAX framework.
|
48
|
+
#
|
49
|
+
# Useful for excluding pages with HTTPS content on them from being loaded
|
50
|
+
# via AJAX.
|
51
|
+
#
|
52
|
+
# <tt>paths</tt> a list of String or Regexp instances that are matched
|
53
|
+
# against each REQUEST_PATH.
|
54
|
+
#
|
55
|
+
# The string and regex paths are modified to match full URLs by prepending
|
56
|
+
# them with the appropriate regular expression.
|
57
|
+
def exclude_paths(paths=nil)
|
58
|
+
if !instance_variable_defined?(:@exclude_paths)
|
59
|
+
@exclude_paths = []
|
60
|
+
end
|
61
|
+
(paths || []).each do |path|
|
62
|
+
@exclude_paths << /^(\w+\:\/\/[^\/]+\/?)?#{path.to_s}$/
|
63
|
+
end
|
64
|
+
@exclude_paths
|
65
|
+
end
|
66
|
+
|
67
|
+
# Return a boolean indicating whether or not to exclude a path from the
|
68
|
+
# AJAX redirect.
|
69
|
+
def exclude_path?(path)
|
70
|
+
!!((@exclude_paths || []).find do |excluded|
|
71
|
+
!!excluded.match(path)
|
72
|
+
end)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Ajax
|
2
|
+
module Helpers
|
3
|
+
module RobotHelper
|
4
|
+
ROBOTS = [
|
5
|
+
{:name => 'Googlebot', :user_agent_regex => /\bGooglebot\b/i, :sample_agent_string => 'Googlebot'},
|
6
|
+
{:name => 'Baidu', :user_agent_regex => /\bBaidu\b/i, :sample_agent_string => 'Baidu'},
|
7
|
+
{:name => 'Gigabot', :user_agent_regex => /\bGigabot\b/i, :sample_agent_string => 'Gigabot'},
|
8
|
+
{:name => 'libwww-perl', :user_agent_regex => /\blibwww-perl\b/i, :sample_agent_string => 'libwww-perl'},
|
9
|
+
{:name => 'lwp-trivial', :user_agent_regex => /\blwp-trivial\b/i, :sample_agent_string => 'lwp-trivial'},
|
10
|
+
{:name => 'MSNBot', :user_agent_regex => /\bmsnbot\b/i, :sample_agent_string => 'msnbot'},
|
11
|
+
{:name => 'SiteUptime', :user_agent_regex => /\bSiteUptime\b/i, :sample_agent_string => 'SiteUptime'},
|
12
|
+
{:name => 'Slurp', :user_agent_regex => /\bSlurp\b/i, :sample_agent_string => 'Slurp'},
|
13
|
+
{:name => 'WordPress', :user_agent_regex => /\bWordPress\b/i, :sample_agent_string => 'WordPress'},
|
14
|
+
{:name => 'ZIBB', :user_agent_regex => /\bZIBB\b/i, :sample_agent_string => 'ZIBB'},
|
15
|
+
{:name => 'ZyBorg', :user_agent_regex => /\bZyBorg\b/i, :sample_agent_string => 'ZyBorg'},
|
16
|
+
]
|
17
|
+
|
18
|
+
def robot_for(user_agent)
|
19
|
+
ROBOTS.each do |r|
|
20
|
+
return r if user_agent =~ r[:user_agent_regex]
|
21
|
+
end
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
|
25
|
+
# Call with a User Agent string
|
26
|
+
def is_robot?(user_agent)
|
27
|
+
!!self.robot_for(user_agent)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Ajax
|
2
|
+
module Helpers
|
3
|
+
module UrlHelper
|
4
|
+
|
5
|
+
# Return a boolean indicating whether the given URL points to the
|
6
|
+
# root path.
|
7
|
+
def url_is_root?(url)
|
8
|
+
!!(URI.parse(url).path =~ %r[^\/?$])
|
9
|
+
end
|
10
|
+
|
11
|
+
# The URL is hashed if the fragment part starts with a /
|
12
|
+
#
|
13
|
+
# For example, http://lol.com#/Rihanna
|
14
|
+
def is_hashed_url?(url)
|
15
|
+
!!(URI.parse(url).fragment =~ %r[^\/])
|
16
|
+
end
|
17
|
+
|
18
|
+
# Return a hashed URL using the fragment of <tt>url</tt>
|
19
|
+
def hashed_url_from_fragment(url)
|
20
|
+
url_host(url) + ('/#/' + (URI.parse(url).fragment || '')).gsub(/\/\//, '/')
|
21
|
+
end
|
22
|
+
|
23
|
+
# Return a traditional URL from the fragment of <tt>url</tt>
|
24
|
+
def traditional_url_from_fragment(url)
|
25
|
+
url_host(url) + ('/' + (URI.parse(url).fragment || '')).gsub(/\/\//, '/')
|
26
|
+
end
|
27
|
+
|
28
|
+
# Return a hashed URL formed from a traditional <tt>url</tt>
|
29
|
+
def hashed_url_from_traditional(url)
|
30
|
+
uri = URI.parse(url)
|
31
|
+
hashed_url = url_host(url) + ('/#/' + (uri.path || '')).gsub(/\/\//, '/')
|
32
|
+
hashed_url += ('?' + uri.query) unless uri.query.nil?
|
33
|
+
hashed_url
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
|
38
|
+
def url_host(url)
|
39
|
+
if url.match(/^(\w+\:\/\/[^\/]+)\/?/)
|
40
|
+
$1
|
41
|
+
else
|
42
|
+
''
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/ajax/railtie.rb
ADDED
data/lib/ajax/routes.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
module Ajax
|
2
|
+
module Routes
|
3
|
+
# In your <tt>config/routes.rb</tt> file call:
|
4
|
+
# Ajax::Routes.draw(map)
|
5
|
+
# Passing in the routing <tt>map</tt> object.
|
6
|
+
#
|
7
|
+
# Adds an <tt>ajax_framework_path</tt> pointing to <tt>/ajax/framework</tt>
|
8
|
+
def self.draw(map)
|
9
|
+
map.ajax_framework "/ajax/framework", :controller => 'ajax', :action => 'framework'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Ajax
|
2
|
+
module Spec
|
3
|
+
module Extension
|
4
|
+
|
5
|
+
def integrate_ajax
|
6
|
+
Ajax.enabled = true
|
7
|
+
end
|
8
|
+
|
9
|
+
def disable_ajax
|
10
|
+
Ajax.enabled = false
|
11
|
+
end
|
12
|
+
|
13
|
+
def mock_ajax
|
14
|
+
integrate_ajax
|
15
|
+
Ajax.mocked = true
|
16
|
+
end
|
17
|
+
|
18
|
+
def unmock_ajax
|
19
|
+
disable_ajax
|
20
|
+
Ajax.mocked = false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module ActiveSupport
|
27
|
+
class TestCase
|
28
|
+
include Ajax::Spec::Extension
|
29
|
+
|
30
|
+
before(:all) do
|
31
|
+
::Ajax.enabled = false
|
32
|
+
end if method_defined?(:before)
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
module Ajax
|
4
|
+
module Spec
|
5
|
+
module Helpers
|
6
|
+
|
7
|
+
def create_app
|
8
|
+
@app = Class.new { def call(env); true; end }.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def call_rack(url, request_method='GET', env={}, &block)
|
12
|
+
env(url, request_method, env)
|
13
|
+
@rack = Rack::Ajax.new(@app, &block)
|
14
|
+
@response = @rack.call(@env)
|
15
|
+
end
|
16
|
+
|
17
|
+
def should_respond_with(msg)
|
18
|
+
should_be_a_valid_response
|
19
|
+
response_body.should == msg
|
20
|
+
end
|
21
|
+
|
22
|
+
def should_redirect_to(location, code=302)
|
23
|
+
should_be_a_valid_response
|
24
|
+
response_code.should == code
|
25
|
+
response_headers['Location'].should == location
|
26
|
+
end
|
27
|
+
|
28
|
+
def should_set_ajax_response_header(key, value)
|
29
|
+
response_headers['Ajax-Info'][key].should == value
|
30
|
+
end
|
31
|
+
|
32
|
+
def should_set_ajax_request_header(key, value)
|
33
|
+
@env['Ajax-Info'][key].should == value
|
34
|
+
end
|
35
|
+
|
36
|
+
def should_rewrite_to(url)
|
37
|
+
should_be_a_valid_response
|
38
|
+
|
39
|
+
# Check custom headers
|
40
|
+
response_body_as_hash['REQUEST_URI'].should == url
|
41
|
+
end
|
42
|
+
|
43
|
+
def should_not_modify_request
|
44
|
+
should_be_a_valid_response
|
45
|
+
response_code.should == 200
|
46
|
+
|
47
|
+
# If we have the original headers from a call to call_rack()
|
48
|
+
# check that they haven't changed. Otherwise, just make sure
|
49
|
+
# that we don't have the custom rewrite header.
|
50
|
+
if !@env.nil?
|
51
|
+
@env.each { |k,v| response_body_as_hash.should == v }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Response must be [code, {headers}, ['Response']]
|
56
|
+
# Headers must contain the Content-Type header
|
57
|
+
def should_be_a_valid_response
|
58
|
+
return if @response.is_a?(::ActionController::Response)
|
59
|
+
@response.should be_a_kind_of(Array)
|
60
|
+
@response.size.should == 3
|
61
|
+
@response[0].should be_a_kind_of(Integer)
|
62
|
+
@response[1].should be_a_kind_of(Hash)
|
63
|
+
@response[1]['Content-Type'].should =~ %r[^text\/\w+]
|
64
|
+
@response[2].should be_a_kind_of(Array)
|
65
|
+
@response[2][0].should be_a_kind_of(String)
|
66
|
+
end
|
67
|
+
|
68
|
+
def env(uri, request_method, options={})
|
69
|
+
uri = URI.parse(uri)
|
70
|
+
@env = {
|
71
|
+
'REQUEST_URI' => uri.to_s,
|
72
|
+
'PATH_INFO' => uri.path,
|
73
|
+
'QUERY_STRING' => uri.query,
|
74
|
+
'REQUEST_METHOD' => request_method
|
75
|
+
}.merge!(options)
|
76
|
+
end
|
77
|
+
|
78
|
+
def response_body
|
79
|
+
@response.is_a?(::ActionController::Response) ? @response.body : @response[2][0]
|
80
|
+
end
|
81
|
+
|
82
|
+
def response_code
|
83
|
+
@response.is_a?(::ActionController::Response) ? @response.status.to_i : @response[0]
|
84
|
+
end
|
85
|
+
|
86
|
+
def response_headers
|
87
|
+
@response.is_a?(::ActionController::Response) ? @response.headers.to_hash : @response[1]
|
88
|
+
end
|
89
|
+
|
90
|
+
def response_body_as_hash
|
91
|
+
@response_body_as_hash ||= YAML.load(response_body)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|