actionpack 0.9.5 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- data/CHANGELOG +177 -0
- data/README +0 -1
- data/install.rb +1 -0
- data/lib/action_controller.rb +6 -1
- data/lib/action_controller/assertions/active_record_assertions.rb +2 -2
- data/lib/action_controller/base.rb +53 -41
- data/lib/action_controller/benchmarking.rb +1 -1
- data/lib/action_controller/cgi_ext/cgi_methods.rb +14 -16
- data/lib/action_controller/cgi_process.rb +16 -6
- data/lib/action_controller/cookies.rb +70 -0
- data/lib/action_controller/dependencies.rb +106 -0
- data/lib/action_controller/helpers.rb +14 -3
- data/lib/action_controller/layout.rb +16 -2
- data/lib/action_controller/request.rb +17 -7
- data/lib/action_controller/rescue.rb +33 -3
- data/lib/action_controller/support/class_inheritable_attributes.rb +4 -0
- data/lib/action_controller/support/inflector.rb +14 -12
- data/lib/action_controller/support/misc.rb +6 -0
- data/lib/action_controller/templates/rescues/_request_and_response.rhtml +2 -2
- data/lib/action_controller/templates/rescues/diagnostics.rhtml +4 -6
- data/lib/action_controller/templates/rescues/template_error.rhtml +1 -9
- data/lib/action_controller/templates/scaffolds/edit.rhtml +2 -1
- data/lib/action_controller/templates/scaffolds/layout.rhtml +36 -0
- data/lib/action_controller/templates/scaffolds/new.rhtml +1 -0
- data/lib/action_controller/test_process.rb +27 -8
- data/lib/action_controller/url_rewriter.rb +15 -4
- data/lib/action_view/base.rb +4 -3
- data/lib/action_view/helpers/active_record_helper.rb +29 -15
- data/lib/action_view/helpers/date_helper.rb +6 -5
- data/lib/action_view/helpers/form_helper.rb +31 -4
- data/lib/action_view/helpers/form_options_helper.rb +13 -3
- data/lib/action_view/helpers/tag_helper.rb +14 -16
- data/lib/action_view/helpers/url_helper.rb +46 -1
- data/lib/action_view/partials.rb +8 -1
- data/lib/action_view/template_error.rb +10 -3
- data/lib/action_view/vendor/builder/blankslate.rb +33 -1
- data/lib/action_view/vendor/builder/xmlevents.rb +1 -1
- data/lib/action_view/vendor/builder/xmlmarkup.rb +1 -1
- data/rakefile +4 -13
- data/test/controller/action_pack_assertions_test.rb +39 -1
- data/test/controller/active_record_assertions_test.rb +6 -5
- data/test/controller/cgi_test.rb +33 -3
- data/test/controller/cookie_test.rb +43 -2
- data/test/controller/helper_test.rb +1 -1
- data/test/controller/render_test.rb +9 -0
- data/test/controller/url_test.rb +16 -0
- data/test/fixtures/scope/test/modgreet.rhtml +1 -0
- data/test/template/active_record_helper_test.rb +34 -8
- data/test/template/date_helper_test.rb +164 -20
- data/test/template/form_helper_test.rb +12 -0
- data/test/template/form_options_helper_test.rb +7 -16
- data/test/template/url_helper_test.rb +12 -0
- metadata +8 -2
@@ -8,15 +8,25 @@ module ActionView
|
|
8
8
|
# the actual select tag, so you'll need to construct that in HTML manually.
|
9
9
|
module FormOptionsHelper
|
10
10
|
include ERB::Util
|
11
|
-
|
11
|
+
|
12
|
+
# Create a select tag and a series of contained option tags for the provided object and method.
|
13
|
+
# The option currenlty held by the object will be selected, provided that the object is available.
|
14
|
+
#
|
15
|
+
# This can be used to provide a default set of options in the standard way: before rendering the create form, a
|
16
|
+
# new model instance is assigned the default options and bound to @model_name. Usually this model is not saved
|
17
|
+
# to the database. Instead, a second model object is created when the create request is received.
|
18
|
+
# This allows the user to submit a form page more than once with the expected results of creating multiple records.
|
19
|
+
# In addition, this allows a single partial to be used to generate form inputs for both edit and create forms.
|
12
20
|
def select(object, method, choices, options = {}, html_options = {})
|
13
21
|
InstanceTag.new(object, method, self).to_select_tag(choices, options, html_options)
|
14
22
|
end
|
15
|
-
|
23
|
+
|
24
|
+
# Return select and option tags for the given object and method using options_from_collection_for_select to generate the list of option tags.
|
16
25
|
def collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})
|
17
26
|
InstanceTag.new(object, method, self).to_collection_select_tag(collection, value_method, text_method, options, html_options)
|
18
27
|
end
|
19
|
-
|
28
|
+
|
29
|
+
# Return select and option tags for the given object and method, using country_options_for_select to generate the list of option tags.
|
20
30
|
def country_select(object, method, priority_countries = nil, options = {}, html_options = {})
|
21
31
|
InstanceTag.new(object, method, self).to_country_select_tag(priority_countries, options, html_options)
|
22
32
|
end
|
@@ -7,24 +7,24 @@ module ActionView
|
|
7
7
|
include ERB::Util
|
8
8
|
|
9
9
|
# Examples:
|
10
|
-
# * tag("br") => <br
|
11
|
-
# * tag("input", { "type" => "text"}) => <input type="text"
|
10
|
+
# * <tt>tag("br") => <br /></tt>
|
11
|
+
# * <tt>tag("input", { "type" => "text"}) => <input type="text" /></tt>
|
12
12
|
def tag(name, options = {}, open = false)
|
13
|
-
"<#{name
|
13
|
+
"<#{name}#{tag_options(options)}" + (open ? ">" : " />")
|
14
14
|
end
|
15
15
|
|
16
16
|
# Examples:
|
17
|
-
# * content_tag("p", "Hello world!") => <p>Hello world!</p>
|
18
|
-
# * content_tag("div", content_tag("p", "Hello world!"), "class" => "strong") =>
|
19
|
-
# <div class="strong"><p>Hello world!</p></div>
|
17
|
+
# * <tt>content_tag("p", "Hello world!") => <p>Hello world!</p></tt>
|
18
|
+
# * <tt>content_tag("div", content_tag("p", "Hello world!"), "class" => "strong") => </tt>
|
19
|
+
# <tt><div class="strong"><p>Hello world!</p></div></tt>
|
20
20
|
def content_tag(name, content, options = {})
|
21
|
-
"<#{name
|
21
|
+
"<#{name}#{tag_options(options)}>#{content}</#{name}>"
|
22
22
|
end
|
23
23
|
|
24
24
|
# Starts a form tag that points the action to an url configured with <tt>url_for_options</tt> just like
|
25
25
|
# ActionController::Base#url_for.
|
26
|
-
def form_tag(url_for_options, options = {}, *parameters_for_url)
|
27
|
-
html_options = { "method" => "
|
26
|
+
def form_tag(url_for_options = {}, options = {}, *parameters_for_url)
|
27
|
+
html_options = { "method" => "post" }.merge(options)
|
28
28
|
|
29
29
|
if html_options[:multipart]
|
30
30
|
html_options["enctype"] = "multipart/form-data"
|
@@ -46,14 +46,12 @@ module ActionView
|
|
46
46
|
|
47
47
|
private
|
48
48
|
def tag_options(options)
|
49
|
-
|
50
|
-
""
|
51
|
-
|
52
|
-
" "
|
53
|
-
"#{pair.first}=\"#{html_escape(pair.last)}\""
|
54
|
-
}.sort.join(" ")
|
49
|
+
unless options.empty?
|
50
|
+
" " + options.map { |key, value|
|
51
|
+
%(#{key}="#{html_escape(value)}")
|
52
|
+
}.sort.join(" ")
|
55
53
|
end
|
56
54
|
end
|
57
55
|
end
|
58
56
|
end
|
59
|
-
end
|
57
|
+
end
|
@@ -8,7 +8,7 @@ module ActionView
|
|
8
8
|
# Returns the URL for the set of +options+ provided. See the valid options in link:classes/ActionController/Base.html#M000021
|
9
9
|
def url_for(options = {}, *parameters_for_method_reference)
|
10
10
|
if Hash === options then options = { :only_path => true }.merge(options) end
|
11
|
-
@controller.send(:url_for, options, *parameters_for_method_reference)
|
11
|
+
@controller.send(:url_for, options, *parameters_for_method_reference)
|
12
12
|
end
|
13
13
|
|
14
14
|
# Creates a link tag of the given +name+ using an URL created by the set of +options+. See the valid options in
|
@@ -25,6 +25,51 @@ module ActionView
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
+
# Creates a link tag to the image residing at the +src+ using an URL created by the set of +options+. See the valid options in
|
29
|
+
# link:classes/ActionController/Base.html#M000021. It's also possible to pass a string instead of an options hash to
|
30
|
+
# get a link tag that just points without consideration. The <tt>html_options</tt> works jointly for the image and ahref tag by
|
31
|
+
# letting the following special values enter the options on the image and the rest goes to the ahref:
|
32
|
+
#
|
33
|
+
# * <tt>alt</tt> - If no alt text is given, the file name part of the +src+ is used (capitalized and without the extension)
|
34
|
+
# * <tt>size</tt> - Supplied as "XxY", so "30x45" becomes width="30" and height="45"
|
35
|
+
# * <tt>border</tt> - Is set to 0 by default
|
36
|
+
# * <tt>align</tt> - Sets the alignment, no special features
|
37
|
+
#
|
38
|
+
# The +src+ can be supplied as a...
|
39
|
+
# * full path, like "/my_images/image.gif"
|
40
|
+
# * file name, like "rss.gif", that gets expanded to "/images/rss.gif"
|
41
|
+
# * file name without extension, like "logo", that gets expanded to "/images/logo.png"
|
42
|
+
def link_to_image(src, options = {}, html_options = {}, *parameters_for_method_reference)
|
43
|
+
image_options = { "src" => src.include?("/") ? src : "/images/#{src}" }
|
44
|
+
image_options["src"] = image_options["src"] + ".png" unless image_options["src"].include?(".")
|
45
|
+
|
46
|
+
if html_options["alt"]
|
47
|
+
image_options["alt"] = html_options["alt"]
|
48
|
+
html_options.delete "alt"
|
49
|
+
else
|
50
|
+
image_options["alt"] = src.split("/").last.split(".").first.capitalize
|
51
|
+
end
|
52
|
+
|
53
|
+
if html_options["size"]
|
54
|
+
image_options["width"], image_options["height"] = html_options["size"].split("x")
|
55
|
+
html_options.delete "size"
|
56
|
+
end
|
57
|
+
|
58
|
+
if html_options["border"]
|
59
|
+
image_options["border"] = html_options["border"]
|
60
|
+
html_options.delete "border"
|
61
|
+
else
|
62
|
+
image_options["border"] = "0"
|
63
|
+
end
|
64
|
+
|
65
|
+
if html_options["align"]
|
66
|
+
image_options["align"] = html_options["align"]
|
67
|
+
html_options.delete "align"
|
68
|
+
end
|
69
|
+
|
70
|
+
link_to(tag("img", image_options), options, html_options, *parameters_for_method_reference)
|
71
|
+
end
|
72
|
+
|
28
73
|
# Creates a link tag of the given +name+ using an URL created by the set of +options+, unless the current
|
29
74
|
# controller, action, and id are the same as the link's, in which case only the name is returned (or the
|
30
75
|
# given block is yielded, if one exists). This is useful for creating link bars where you don't want to link
|
data/lib/action_view/partials.rb
CHANGED
@@ -34,13 +34,16 @@ module ActionView
|
|
34
34
|
def render_partial(partial_path, object = nil, local_assigns = {})
|
35
35
|
path, partial_name = partial_pieces(partial_path)
|
36
36
|
object ||= controller.instance_variable_get("@#{partial_name}")
|
37
|
+
counter_name = partial_counter_name(partial_name)
|
38
|
+
local_assigns = local_assigns.merge(counter_name => 1) unless local_assigns.has_key?(counter_name)
|
37
39
|
render("#{path}/_#{partial_name}", { partial_name => object }.merge(local_assigns))
|
38
40
|
end
|
39
41
|
|
40
42
|
def render_collection_of_partials(partial_name, collection, partial_spacer_template = nil)
|
41
43
|
collection_of_partials = Array.new
|
44
|
+
counter_name = partial_counter_name(partial_name)
|
42
45
|
collection.each_with_index do |element, counter|
|
43
|
-
collection_of_partials.push(render_partial(partial_name, element,
|
46
|
+
collection_of_partials.push(render_partial(partial_name, element, counter_name => counter))
|
44
47
|
end
|
45
48
|
|
46
49
|
return nil if collection_of_partials.empty?
|
@@ -60,5 +63,9 @@ module ActionView
|
|
60
63
|
return controller.send(:controller_name), partial_path
|
61
64
|
end
|
62
65
|
end
|
66
|
+
|
67
|
+
def partial_counter_name(partial_name)
|
68
|
+
"#{partial_name.split('/').last}_counter"
|
69
|
+
end
|
63
70
|
end
|
64
71
|
end
|
@@ -28,7 +28,7 @@ module ActionView
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
def source_extract
|
31
|
+
def source_extract(indention = 0)
|
32
32
|
source_code = IO.readlines(@file_name)
|
33
33
|
|
34
34
|
start_on_line = [ line_number - SOURCE_CODE_RADIUS - 1, 0 ].max
|
@@ -37,9 +37,9 @@ module ActionView
|
|
37
37
|
line_counter = start_on_line
|
38
38
|
extract = source_code[start_on_line..end_on_line].collect do |line|
|
39
39
|
line_counter += 1
|
40
|
-
"#{line_counter}: " + line
|
40
|
+
"#{' ' * indention}#{line_counter}: " + line
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
extract.join
|
44
44
|
end
|
45
45
|
|
@@ -71,6 +71,13 @@ module ActionView
|
|
71
71
|
"\n\n"
|
72
72
|
end
|
73
73
|
|
74
|
+
def backtrace
|
75
|
+
[
|
76
|
+
"On line ##{line_number} of #{file_name}\n\n#{source_extract(4)}\n " +
|
77
|
+
clean_backtrace(original_exception).join("\n ")
|
78
|
+
]
|
79
|
+
end
|
80
|
+
|
74
81
|
private
|
75
82
|
def strip_base_path(file_name)
|
76
83
|
file_name.gsub(@base_path, "")
|
@@ -15,7 +15,39 @@ module Builder #:nodoc:
|
|
15
15
|
# BlankSlate is useful as a base class when writing classes that
|
16
16
|
# depend upon <tt>method_missing</tt> (e.g. dynamic proxies).
|
17
17
|
class BlankSlate #:nodoc:
|
18
|
-
|
18
|
+
class << self
|
19
|
+
def hide(name)
|
20
|
+
undef_method name if
|
21
|
+
instance_methods.include?(name.to_s) and
|
22
|
+
name !~ /^(__|instance_eval)/
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
instance_methods.each { |m| hide(m) }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Since Ruby is very dynamic, methods added to the ancestors of
|
31
|
+
# BlankSlate <em>after BlankSlate is defined</em> will show up in the
|
32
|
+
# list of available BlankSlate methods. We handle this by defining a hook in the Object and Kernel classes that will hide any defined
|
33
|
+
module Kernel #:nodoc:
|
34
|
+
class << self
|
35
|
+
alias_method :blank_slate_method_added, :method_added
|
36
|
+
def method_added(name)
|
37
|
+
blank_slate_method_added(name)
|
38
|
+
return if self != Kernel
|
39
|
+
Builder::BlankSlate.hide(name)
|
40
|
+
end
|
19
41
|
end
|
42
|
+
end
|
20
43
|
|
44
|
+
class Object #:nodoc:
|
45
|
+
class << self
|
46
|
+
alias_method :blank_slate_method_added, :method_added
|
47
|
+
def method_added(name)
|
48
|
+
blank_slate_method_added(name)
|
49
|
+
return if self != Object
|
50
|
+
Builder::BlankSlate.hide(name)
|
51
|
+
end
|
52
|
+
end
|
21
53
|
end
|
data/rakefile
CHANGED
@@ -8,7 +8,7 @@ require 'rake/contrib/rubyforgepublisher'
|
|
8
8
|
|
9
9
|
PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
|
10
10
|
PKG_NAME = 'actionpack'
|
11
|
-
PKG_VERSION = '0.
|
11
|
+
PKG_VERSION = '1.0.0' + PKG_BUILD
|
12
12
|
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
13
13
|
|
14
14
|
desc "Default Task"
|
@@ -58,7 +58,7 @@ spec = Gem::Specification.new do |s|
|
|
58
58
|
|
59
59
|
s.files = [ "rakefile", "install.rb", "README", "RUNNING_UNIT_TESTS", "CHANGELOG", "MIT-LICENSE", "examples/.htaccess" ]
|
60
60
|
dist_dirs.each do |dir|
|
61
|
-
s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "
|
61
|
+
s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) }
|
62
62
|
end
|
63
63
|
s.files.delete "examples/benchmark.rb"
|
64
64
|
s.files.delete "examples/benchmark_with_ar.fcgi"
|
@@ -75,6 +75,7 @@ end
|
|
75
75
|
desc "Publish the API documentation"
|
76
76
|
task :pgem => [:package] do
|
77
77
|
Rake::SshFilePublisher.new("davidhh@one.textdrive.com", "domains/rubyonrails.org/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
|
78
|
+
`ssh davidhh@one.textdrive.com './gemupdate.sh'`
|
78
79
|
end
|
79
80
|
|
80
81
|
# Publish documentation
|
@@ -83,11 +84,6 @@ task :pdoc => [:rdoc] do
|
|
83
84
|
Rake::SshDirPublisher.new("davidhh@one.textdrive.com", "domains/rubyonrails.org/ap", "doc").upload
|
84
85
|
end
|
85
86
|
|
86
|
-
desc "Publish to RubyForge"
|
87
|
-
task :rubyforge do
|
88
|
-
Rake::RubyForgePublisher.new('actionpack', 'webster132').upload
|
89
|
-
end
|
90
|
-
|
91
87
|
|
92
88
|
desc "Count lines in the main rake file"
|
93
89
|
task :lines do
|
@@ -106,9 +102,4 @@ task :lines do
|
|
106
102
|
end
|
107
103
|
}
|
108
104
|
puts "Lines #{lines}, LOC #{codelines}"
|
109
|
-
end
|
110
|
-
|
111
|
-
desc "Publish to RubyForge"
|
112
|
-
task :rubyforge do
|
113
|
-
Rake::RubyForgePublisher.new('activecontrol', 'webster132').upload
|
114
|
-
end
|
105
|
+
end
|
@@ -54,6 +54,18 @@ class ActionPackAssertionsController < ActionController::Base
|
|
54
54
|
session['xmas'] = 'turkey'
|
55
55
|
render_text "ho ho ho"
|
56
56
|
end
|
57
|
+
|
58
|
+
# raises exception on get requests
|
59
|
+
def raise_on_get
|
60
|
+
raise "get" if @request.get?
|
61
|
+
render_text "request method: #{@request.env['REQUEST_METHOD']}"
|
62
|
+
end
|
63
|
+
|
64
|
+
# raises exception on post requests
|
65
|
+
def raise_on_post
|
66
|
+
raise "post" if @request.post?
|
67
|
+
render_text "request method: #{@request.env['REQUEST_METHOD']}"
|
68
|
+
end
|
57
69
|
|
58
70
|
# 911
|
59
71
|
def rescue_action(e) raise; end
|
@@ -70,7 +82,7 @@ ActionPackAssertionsController.template_root = File.dirname(__FILE__) + "/../fix
|
|
70
82
|
|
71
83
|
|
72
84
|
# a test case to exercise the new capabilities TestRequest & TestResponse
|
73
|
-
class ActionPackAssertionsControllerTest < Test::Unit::TestCase
|
85
|
+
class ActionPackAssertionsControllerTest < Test::Unit::TestCase
|
74
86
|
# let's get this party started
|
75
87
|
def setup
|
76
88
|
@controller = ActionPackAssertionsController.new
|
@@ -85,6 +97,32 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
|
|
85
97
|
assert_session_has 'xmas'
|
86
98
|
assert_session_has_no 'halloween'
|
87
99
|
end
|
100
|
+
|
101
|
+
# test the get method, make sure the request really was a get
|
102
|
+
def test_get
|
103
|
+
assert_raise(RuntimeError) { get :raise_on_get }
|
104
|
+
get :raise_on_post
|
105
|
+
assert_equal @response.body, 'request method: GET'
|
106
|
+
end
|
107
|
+
|
108
|
+
# test the get method, make sure the request really was a get
|
109
|
+
def test_post
|
110
|
+
assert_raise(RuntimeError) { post :raise_on_post }
|
111
|
+
post :raise_on_get
|
112
|
+
assert_equal @response.body, 'request method: POST'
|
113
|
+
end
|
114
|
+
|
115
|
+
# test the get/post switch within one test action
|
116
|
+
def test_get_post_switch
|
117
|
+
post :raise_on_get
|
118
|
+
assert_equal @response.body, 'request method: POST'
|
119
|
+
get :raise_on_post
|
120
|
+
assert_equal @response.body, 'request method: GET'
|
121
|
+
post :raise_on_get
|
122
|
+
assert_equal @response.body, 'request method: POST'
|
123
|
+
get :raise_on_post
|
124
|
+
assert_equal @response.body, 'request method: GET'
|
125
|
+
end
|
88
126
|
|
89
127
|
# test the assertion of goodies in the template
|
90
128
|
def test_assert_template_has
|
@@ -21,11 +21,12 @@ require 'fixtures/company'
|
|
21
21
|
|
22
22
|
# add some validation rules to trip up the assertions
|
23
23
|
class Company
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
24
|
+
protected
|
25
|
+
def validate
|
26
|
+
errors.add_on_empty('name')
|
27
|
+
errors.add('rating', 'rating should not be 2') if rating == 2
|
28
|
+
errors.add_to_base('oh oh') if rating == 3
|
29
|
+
end
|
29
30
|
end
|
30
31
|
|
31
32
|
# -----------------------------------------------------------------------------
|
data/test/controller/cgi_test.rb
CHANGED
@@ -133,10 +133,40 @@ class CGITest < Test::Unit::TestCase
|
|
133
133
|
end
|
134
134
|
|
135
135
|
def test_parse_params_with_array
|
136
|
-
|
136
|
+
input = { "selected[]" => [ "1", "2", "3" ] }
|
137
137
|
|
138
|
-
|
138
|
+
expected_output = { "selected" => [ "1", "2", "3" ] }
|
139
139
|
|
140
|
-
|
140
|
+
assert_equal expected_output, CGIMethods.parse_request_parameters(input)
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_parse_params_with_non_alphanumeric_name
|
144
|
+
input = { "a/b[c]" => %w(d) }
|
145
|
+
expected = { "a/b" => { "c" => "d" }}
|
146
|
+
assert_equal expected, CGIMethods.parse_request_parameters(input)
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_parse_params_with_single_brackets_in_middle
|
150
|
+
input = { "a/b[c]d" => %w(e) }
|
151
|
+
expected = { "a/b[c]d" => "e" }
|
152
|
+
assert_equal expected, CGIMethods.parse_request_parameters(input)
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_parse_params_with_separated_brackets
|
156
|
+
input = { "a/b@[c]d[e]" => %w(f) }
|
157
|
+
expected = { "a/b@" => { "c]d[e" => "f" }}
|
158
|
+
assert_equal expected, CGIMethods.parse_request_parameters(input)
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_parse_params_with_separated_brackets_and_array
|
162
|
+
input = { "a/b@[c]d[e][]" => %w(f) }
|
163
|
+
expected = { "a/b@" => { "c]d[e" => ["f"] }}
|
164
|
+
assert_equal expected , CGIMethods.parse_request_parameters(input)
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_parse_params_with_unmatched_brackets_and_array
|
168
|
+
input = { "a/b@[c][d[e][]" => %w(f) }
|
169
|
+
expected = { "a/b@" => { "c" => { "d[e" => ["f"] }}}
|
170
|
+
assert_equal expected, CGIMethods.parse_request_parameters(input)
|
141
171
|
end
|
142
172
|
end
|
@@ -2,11 +2,32 @@ require File.dirname(__FILE__) + '/../abstract_unit'
|
|
2
2
|
|
3
3
|
class CookieTest < Test::Unit::TestCase
|
4
4
|
class TestController < ActionController::Base
|
5
|
-
def
|
5
|
+
def authenticate_with_deprecated_writer
|
6
6
|
cookie "name" => "user_name", "value" => "david"
|
7
7
|
render_text "hello world"
|
8
8
|
end
|
9
9
|
|
10
|
+
def authenticate
|
11
|
+
cookies["user_name"] = "david"
|
12
|
+
render_text "hello world"
|
13
|
+
end
|
14
|
+
|
15
|
+
def authenticate_for_fourten_days
|
16
|
+
cookies["user_name"] = { "value" => "david", "expires" => Time.local(2005, 10, 10) }
|
17
|
+
render_text "hello world"
|
18
|
+
end
|
19
|
+
|
20
|
+
def authenticate_for_fourten_days_with_symbols
|
21
|
+
cookies[:user_name] = { :value => "david", :expires => Time.local(2005, 10, 10) }
|
22
|
+
render_text "hello world"
|
23
|
+
end
|
24
|
+
|
25
|
+
def set_multiple_cookies
|
26
|
+
cookies["user_name"] = { "value" => "david", "expires" => Time.local(2005, 10, 10) }
|
27
|
+
cookies["login"] = "XJ-122"
|
28
|
+
render_text "hello world"
|
29
|
+
end
|
30
|
+
|
10
31
|
def access_frozen_cookies
|
11
32
|
@cookies["wont"] = "work"
|
12
33
|
end
|
@@ -21,12 +42,32 @@ class CookieTest < Test::Unit::TestCase
|
|
21
42
|
@request.host = "www.nextangle.com"
|
22
43
|
end
|
23
44
|
|
45
|
+
def test_setting_cookie_with_deprecated_writer
|
46
|
+
@request.action = "authenticate_with_deprecated_writer"
|
47
|
+
assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "david") ], process_request.headers["cookie"]
|
48
|
+
end
|
49
|
+
|
24
50
|
def test_setting_cookie
|
25
51
|
@request.action = "authenticate"
|
26
52
|
assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "david") ], process_request.headers["cookie"]
|
27
53
|
end
|
28
54
|
|
29
|
-
def
|
55
|
+
def test_setting_cookie_for_fourteen_days
|
56
|
+
@request.action = "authenticate_for_fourten_days"
|
57
|
+
assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "david", "expires" => Time.local(2005, 10, 10)) ], process_request.headers["cookie"]
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_setting_cookie_for_fourteen_days_with_symbols
|
61
|
+
@request.action = "authenticate_for_fourten_days"
|
62
|
+
assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "david", "expires" => Time.local(2005, 10, 10)) ], process_request.headers["cookie"]
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_multiple_cookies
|
66
|
+
@request.action = "set_multiple_cookies"
|
67
|
+
assert_equal 2, process_request.headers["cookie"].size
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_setting_cookie_on_frozen_instance_variable
|
30
71
|
@request.action = "access_frozen_cookies"
|
31
72
|
assert_raises(TypeError) { process_request }
|
32
73
|
end
|