actionpack 1.3.1 → 1.4.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 +64 -0
- data/install.rb +12 -3
- data/lib/action_controller/base.rb +19 -4
- data/lib/action_controller/caching.rb +7 -7
- data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +46 -0
- data/lib/action_controller/cgi_process.rb +1 -0
- data/lib/action_controller/dependencies.rb +3 -2
- data/lib/action_controller/filters.rb +4 -4
- data/lib/action_controller/helpers.rb +1 -1
- data/lib/action_controller/request.rb +17 -9
- data/lib/action_controller/support/binding_of_caller.rb +83 -85
- data/lib/action_controller/support/breakpoint.rb +42 -51
- data/lib/action_controller/support/core_ext/object_and_class.rb +24 -0
- data/lib/action_controller/support/dependencies.rb +20 -15
- data/lib/action_controller/test_process.rb +17 -0
- data/lib/action_controller/url_rewriter.rb +2 -1
- data/lib/action_view/helpers/cache_helper.rb +2 -2
- data/lib/action_view/helpers/form_helper.rb +6 -0
- data/lib/action_view/helpers/url_helper.rb +28 -1
- data/lib/action_view/vendor/builder/xmlmarkup.rb +15 -6
- data/rakefile +1 -1
- data/test/controller/filters_test.rb +20 -0
- data/test/controller/raw_post_test.rb +31 -0
- data/test/controller/url_test.rb +21 -0
- data/test/template/form_helper_test.rb +26 -0
- data/test/template/tag_helper_test.rb +12 -0
- metadata +5 -2
data/CHANGELOG
CHANGED
@@ -1,3 +1,67 @@
|
|
1
|
+
*1.4.0* (January 25th, 2005)
|
2
|
+
|
3
|
+
* Fixed problems with ActiveRecordStore under the development environment in Rails
|
4
|
+
|
5
|
+
* Fixed the ordering of attributes in the xml-decleration of Builder #540 [woeye]
|
6
|
+
|
7
|
+
* Added @request.raw_post as a convenience access to @request.env['RAW_POST_DATA'] #534 [Tobias Luetke]
|
8
|
+
|
9
|
+
* Added support for automatic id-based indexing for lists of items #532 [dblack]. Example:
|
10
|
+
|
11
|
+
<% @students.each do |@student| %>
|
12
|
+
<%= text_field "student[]", "first_name", :size => "20" %>
|
13
|
+
<%= text_field "student[]", "last_name" %>
|
14
|
+
<%= text_field "student[]", "grade", :size => "5" %>
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
...would produce, for say David Black with id 123 and a grace of C+:
|
18
|
+
|
19
|
+
<input id="student_123_first_name" name="student[123][first_name]" size="20" size="30" type="text" value="David" />
|
20
|
+
<input id="student_123_last_name" name="student[123][last_name]" size="30" type="text" value="Black" />
|
21
|
+
<input id="student_123_grade" name="student[123][grade]" size="5" type="text" value="C+" />
|
22
|
+
|
23
|
+
* Added :application_prefix to url_for and friends that makes it easier to setup Rails in non-vhost environments #516 [Jamis Buck]
|
24
|
+
|
25
|
+
* Added :encode option to mail_to that'll allow you to masquarede the email address behind javascript or hex encoding #494 [Lucas Carlson]
|
26
|
+
|
27
|
+
* Fixed that the content-header was being set to application/octet_stream instead of application/octet-stream on send_date/file [Alexey]
|
28
|
+
|
29
|
+
* Removed the need for passing the binding when using CacheHelper#cache
|
30
|
+
|
31
|
+
* Added TestResponse#binary_content that'll return as a string the data sent through send_data/send_file for testing #500 [Alexey]
|
32
|
+
|
33
|
+
* Added @request.env['RAW_POST_DATA'] for people who need access to the data before Ruby's CGI has parsed it #505 [bitsweat]
|
34
|
+
|
35
|
+
* Fixed that a default fragment store wan't being set to MemoryStore as intended.
|
36
|
+
|
37
|
+
* Fixed that all redirect and render calls now return true, so you can use the pattern of "do and return". Example:
|
38
|
+
|
39
|
+
def show
|
40
|
+
redirect_to(:action => "login") and return unless @person.authenticated?
|
41
|
+
render_text "I won't happen unless the person is authenticated"
|
42
|
+
end
|
43
|
+
|
44
|
+
* Added that renders and redirects called in before_filters will have the same effect as returning false: stopping the chain. Example:
|
45
|
+
|
46
|
+
class WeblogController
|
47
|
+
before_filter { |c| c.send(:redirect_to_url("http://www.farfaraway.com")}) }
|
48
|
+
|
49
|
+
def hello
|
50
|
+
render_text "I will never be called"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
* Added that only one render or redirect can happen per action. The first call wins and subsequent calls are ignored. Example:
|
56
|
+
|
57
|
+
def do_something
|
58
|
+
redirect_to :action => "elsewhere"
|
59
|
+
render_action "overthere"
|
60
|
+
end
|
61
|
+
|
62
|
+
Only the redirect happens. The rendering call is simply ignored.
|
63
|
+
|
64
|
+
|
1
65
|
*1.3.1* (January 18th, 2005)
|
2
66
|
|
3
67
|
* Fixed a bug where cookies wouldn't be set if a symbol was used instead of a string as the key
|
data/install.rb
CHANGED
@@ -19,7 +19,8 @@ unless $sitedir
|
|
19
19
|
end
|
20
20
|
|
21
21
|
makedirs = %w{ action_controller/assertions action_controller/cgi_ext
|
22
|
-
action_controller/session action_controller/support action_controller/support/core_ext
|
22
|
+
action_controller/session action_controller/support action_controller/support/core_ext
|
23
|
+
action_controller/support/core_ext/hash action_controller/support/core_ext/numeric action_controller/support/core_ext/string
|
23
24
|
action_controller/templates action_controller/templates/rescues
|
24
25
|
action_controller/templates/scaffolds
|
25
26
|
action_view/helpers action_view/vendor action_view/vendor/builder
|
@@ -41,6 +42,7 @@ files = %w-
|
|
41
42
|
action_controller/cgi_ext/cgi_ext.rb
|
42
43
|
action_controller/cgi_ext/cgi_methods.rb
|
43
44
|
action_controller/cgi_ext/cookie_performance_fix.rb
|
45
|
+
action_controller/cgi_ext/raw_post_data_fix.rb
|
44
46
|
action_controller/caching.rb
|
45
47
|
action_controller/cgi_process.rb
|
46
48
|
action_controller/cookies.rb
|
@@ -61,8 +63,15 @@ files = %w-
|
|
61
63
|
action_controller/support/class_inheritable_attributes.rb
|
62
64
|
action_controller/support/class_attribute_accessors.rb
|
63
65
|
action_controller/support/clean_logger.rb
|
64
|
-
action_controller/support/core_ext/
|
65
|
-
action_controller/support/core_ext.rb
|
66
|
+
action_controller/support/core_ext/hash/keys.rb
|
67
|
+
action_controller/support/core_ext/hash.rb
|
68
|
+
action_controller/support/core_ext/object_and_class.rb
|
69
|
+
action_controller/support/core_ext/numeric/bytes.rb
|
70
|
+
action_controller/support/core_ext/numeric/time.rb
|
71
|
+
action_controller/support/core_ext/numeric.rb
|
72
|
+
action_controller/support/core_ext/string/inflections.rb
|
73
|
+
action_controller/support/core_ext/string.rb
|
74
|
+
active_record/support/core_ext.rb
|
66
75
|
action_controller/support/inflector.rb
|
67
76
|
action_controller/support/binding_of_caller.rb
|
68
77
|
action_controller/support/breakpoint.rb
|
@@ -163,6 +163,17 @@ module ActionController #:nodoc:
|
|
163
163
|
# For more examples of redirecting options, have a look at the unit test in test/controller/url_test.rb. It's very readable and will give
|
164
164
|
# you an excellent understanding of the different options and what they do.
|
165
165
|
#
|
166
|
+
# == Calling multiple redirects or renders
|
167
|
+
#
|
168
|
+
# The rule for handling calls of multiple redirects and renders is that the first call wins. So in the following example:
|
169
|
+
#
|
170
|
+
# def do_something
|
171
|
+
# redirect_to :action => "elsewhere"
|
172
|
+
# render_action "overthere"
|
173
|
+
# end
|
174
|
+
#
|
175
|
+
# Only the redirect happens. The rendering call is simply ignored.
|
176
|
+
#
|
166
177
|
# == Environments
|
167
178
|
#
|
168
179
|
# Action Controller works out of the box with CGI, FastCGI, and mod_ruby. CGI and mod_ruby controllers are triggered just the same using:
|
@@ -178,7 +189,7 @@ module ActionController #:nodoc:
|
|
178
189
|
DEFAULT_RENDER_STATUS_CODE = "200 OK"
|
179
190
|
|
180
191
|
DEFAULT_SEND_FILE_OPTIONS = {
|
181
|
-
:type => 'application/
|
192
|
+
:type => 'application/octet-stream'.freeze,
|
182
193
|
:disposition => 'attachment'.freeze,
|
183
194
|
:stream => true,
|
184
195
|
:buffer_size => 4096
|
@@ -385,11 +396,11 @@ module ActionController #:nodoc:
|
|
385
396
|
# considerably faster than rendering through the template engine.
|
386
397
|
# Use block for response body if provided (useful for deferred rendering or streaming output).
|
387
398
|
def render_text(text = nil, status = nil, &block) #:doc:
|
399
|
+
return if performed?
|
388
400
|
add_variables_to_assigns
|
389
401
|
@response.headers["Status"] = status || DEFAULT_RENDER_STATUS_CODE
|
390
402
|
@response.body = block_given? ? block : text
|
391
403
|
@performed_render = true
|
392
|
-
return false
|
393
404
|
end
|
394
405
|
|
395
406
|
# Renders an empty response that can be used when the request is only interested in triggering an effect. Do note that good
|
@@ -541,10 +552,10 @@ module ActionController #:nodoc:
|
|
541
552
|
# <tt>redirect_to_url "http://www.rubyonrails.org"</tt>. If the resource has moved permanently, it's possible to pass true as the
|
542
553
|
# second parameter and the browser will get "301 Moved Permanently" instead of "302 Found".
|
543
554
|
def redirect_to_url(url, permanently = false) #:doc:
|
555
|
+
return if performed?
|
544
556
|
logger.info("Redirected to #{url}") unless logger.nil?
|
545
557
|
@response.redirect(url, permanently)
|
546
558
|
@performed_redirect = true
|
547
|
-
return false
|
548
559
|
end
|
549
560
|
|
550
561
|
# Resets the session by clearsing out all the objects stored within and initializing a new session object.
|
@@ -594,13 +605,17 @@ module ActionController #:nodoc:
|
|
594
605
|
def perform_action
|
595
606
|
if action_methods.include?(action_name) || action_methods.include?('method_missing')
|
596
607
|
send(action_name)
|
597
|
-
render unless
|
608
|
+
render unless performed?
|
598
609
|
elsif template_exists? && template_public?
|
599
610
|
render
|
600
611
|
else
|
601
612
|
raise UnknownAction, "No action responded to #{action_name}", caller
|
602
613
|
end
|
603
614
|
end
|
615
|
+
|
616
|
+
def performed?
|
617
|
+
@performed_render || @performed_redirect
|
618
|
+
end
|
604
619
|
|
605
620
|
def action_methods
|
606
621
|
action_controller_classes = self.class.ancestors.reject{ |a| [Object, Kernel].include?(a) }
|
@@ -193,7 +193,7 @@ module ActionController #:nodoc:
|
|
193
193
|
# parties. The caching is doing using the cache helper available in the Action View. A template with caching might look something like:
|
194
194
|
#
|
195
195
|
# <b>Hello <%= @name %></b>
|
196
|
-
# <% cache
|
196
|
+
# <% cache do %>
|
197
197
|
# All the topics in the system:
|
198
198
|
# <%= render_collection_of_partials "topic", Topic.find_all %>
|
199
199
|
# <% end %>
|
@@ -203,7 +203,7 @@ module ActionController #:nodoc:
|
|
203
203
|
# if you need to cache multiple fragments per action or if the action itself is cached using <tt>caches_action</tt>. So instead we should
|
204
204
|
# qualify the name of the action used with something like:
|
205
205
|
#
|
206
|
-
# <% cache(
|
206
|
+
# <% cache(:action => "list", :action_suffix => "all_topics") do %>
|
207
207
|
#
|
208
208
|
# That would result in a name such as "/topics/list/all_topics", which wouldn't conflict with any action cache and neither with another
|
209
209
|
# fragment using a different suffix. Note that the URL doesn't have to really exist or be callable. We're just using the url_for system
|
@@ -241,22 +241,22 @@ module ActionController #:nodoc:
|
|
241
241
|
def self.append_features(base) #:nodoc:
|
242
242
|
super
|
243
243
|
base.class_eval do
|
244
|
-
@@
|
244
|
+
@@fragment_cache_store = MemoryStore.new
|
245
245
|
cattr_accessor :fragment_cache_store
|
246
246
|
end
|
247
247
|
end
|
248
248
|
|
249
249
|
# Called by CacheHelper#cache
|
250
|
-
def cache_erb_fragment(
|
251
|
-
unless perform_caching then
|
250
|
+
def cache_erb_fragment(block, name = {}, options = {})
|
251
|
+
unless perform_caching then block.call; return end
|
252
252
|
|
253
|
-
buffer = eval("_erbout", binding)
|
253
|
+
buffer = eval("_erbout", block.binding)
|
254
254
|
|
255
255
|
if cache = read_fragment(name, options)
|
256
256
|
buffer.concat(cache)
|
257
257
|
else
|
258
258
|
pos = buffer.length
|
259
|
-
|
259
|
+
block.call
|
260
260
|
write_fragment(name, buffer[pos..-1], options)
|
261
261
|
end
|
262
262
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class CGI #:nodoc:
|
2
|
+
# Add @request.env['RAW_POST_DATA'] for the vegans.
|
3
|
+
module QueryExtension
|
4
|
+
# Initialize the data from the query.
|
5
|
+
#
|
6
|
+
# Handles multipart forms (in particular, forms that involve file uploads).
|
7
|
+
# Reads query parameters in the @params field, and cookies into @cookies.
|
8
|
+
def initialize_query()
|
9
|
+
if boundary = multipart_form_boundary
|
10
|
+
@multipart = true
|
11
|
+
@params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH']))
|
12
|
+
else
|
13
|
+
@multipart = false
|
14
|
+
@params = CGI::parse(read_query_params)
|
15
|
+
end
|
16
|
+
|
17
|
+
@cookies = CGI::Cookie::parse((env_table['HTTP_COOKIE'] or env_table['COOKIE']))
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
MULTIPART_FORM_BOUNDARY_RE = %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n #"
|
22
|
+
|
23
|
+
def multipart_form_boundary
|
24
|
+
if env_table['REQUEST_METHOD'] == 'POST'
|
25
|
+
MULTIPART_FORM_BOUNDARY_RE.match(env_table['CONTENT_TYPE']).to_a.pop
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def read_query_params
|
30
|
+
case env_table['REQUEST_METHOD']
|
31
|
+
when 'GET', 'HEAD'
|
32
|
+
if defined? MOD_RUBY
|
33
|
+
Apache::request.args or ''
|
34
|
+
else
|
35
|
+
env_table['QUERY_STRING'] or ''
|
36
|
+
end
|
37
|
+
when 'POST'
|
38
|
+
stdinput.binmode if stdinput.respond_to?(:binmode)
|
39
|
+
content = stdinput.read(Integer(env_table['CONTENT_LENGTH'])) or ''
|
40
|
+
env_table['RAW_POST_DATA'] = content.freeze
|
41
|
+
else
|
42
|
+
read_from_cmdline
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end # module QueryExtension
|
46
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'action_controller/cgi_ext/cgi_ext'
|
2
2
|
require 'action_controller/cgi_ext/cookie_performance_fix'
|
3
|
+
require 'action_controller/cgi_ext/raw_post_data_fix'
|
3
4
|
require 'action_controller/session/drb_store'
|
4
5
|
require 'action_controller/session/active_record_store'
|
5
6
|
require 'action_controller/session/mem_cache_store'
|
@@ -78,8 +78,9 @@ module ActionController #:nodoc:
|
|
78
78
|
inherited_without_model(child)
|
79
79
|
return if child.controller_name == "application" # otherwise the ApplicationController in Rails will include itself
|
80
80
|
begin
|
81
|
-
|
82
|
-
|
81
|
+
Object.const_get(child.controller_name.singularize.classify)
|
82
|
+
child.model(child.controller_name.singularize)
|
83
|
+
rescue NameError, LoadError
|
83
84
|
# No neither singular or plural model available for this controller
|
84
85
|
end
|
85
86
|
end
|
@@ -12,9 +12,9 @@ module ActionController #:nodoc:
|
|
12
12
|
#
|
13
13
|
# Filters have access to the request, response, and all the instance variables set by other filters in the chain
|
14
14
|
# or by the action (in the case of after filters). Additionally, it's possible for a pre-processing <tt>before_filter</tt>
|
15
|
-
# to halt the processing before the intended action is processed by returning false
|
16
|
-
# filters like authentication where you're not interested in allowing the action to be
|
17
|
-
# credentials are not in order.
|
15
|
+
# to halt the processing before the intended action is processed by returning false or performing a redirect or render.
|
16
|
+
# This is especially useful for filters like authentication where you're not interested in allowing the action to be
|
17
|
+
# performed if the proper credentials are not in order.
|
18
18
|
#
|
19
19
|
# == Filter inheritance
|
20
20
|
#
|
@@ -290,7 +290,7 @@ module ActionController #:nodoc:
|
|
290
290
|
end
|
291
291
|
|
292
292
|
def perform_action_with_filters
|
293
|
-
return if before_action == false
|
293
|
+
return if before_action == false || performed?
|
294
294
|
perform_action_without_filters
|
295
295
|
after_action
|
296
296
|
end
|
@@ -29,7 +29,8 @@ module ActionController
|
|
29
29
|
def head?
|
30
30
|
method == :head
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
|
+
|
33
34
|
# Determine originating IP address. REMOTE_ADDR is the standard
|
34
35
|
# but will fail if the user is behind a proxy. HTTP_CLIENT_IP and/or
|
35
36
|
# HTTP_X_FORWARDED_FOR are set by proxies so check for these before
|
@@ -53,40 +54,47 @@ module ActionController
|
|
53
54
|
# Returns the domain part of a host, such as rubyonrails.org in "www.rubyonrails.org". You can specify
|
54
55
|
# a different <tt>tld_length</tt>, such as 2 to catch rubyonrails.co.uk in "www.rubyonrails.co.uk".
|
55
56
|
def domain(tld_length = 1)
|
56
|
-
host.split(
|
57
|
+
host.split('.').last(1 + tld_length).join('.')
|
57
58
|
end
|
58
59
|
|
59
60
|
# Returns all the subdomains as an array, so ["dev", "www"] would be returned for "dev.www.rubyonrails.org".
|
60
61
|
# You can specify a different <tt>tld_length</tt>, such as 2 to catch ["www"] instead of ["www", "rubyonrails"]
|
61
62
|
# in "www.rubyonrails.co.uk".
|
62
63
|
def subdomains(tld_length = 1)
|
63
|
-
parts = host.split(
|
64
|
+
parts = host.split('.')
|
64
65
|
parts - parts.last(1 + tld_length)
|
65
66
|
end
|
66
67
|
|
68
|
+
# Recieve the raw post data.
|
69
|
+
# This is useful for services such as REST, XMLRPC and SOAP
|
70
|
+
# which communicate over HTTP POST but don't use the traditional parameter format.
|
71
|
+
def raw_post
|
72
|
+
env['RAW_POST_DATA']
|
73
|
+
end
|
74
|
+
|
67
75
|
def request_uri
|
68
|
-
env[
|
76
|
+
env['REQUEST_URI']
|
69
77
|
end
|
70
78
|
|
71
79
|
def protocol
|
72
|
-
port == 443 ?
|
80
|
+
port == 443 ? 'https://' : 'http://'
|
73
81
|
end
|
74
82
|
|
75
83
|
def ssl?
|
76
|
-
protocol ==
|
84
|
+
protocol == 'https://'
|
77
85
|
end
|
78
86
|
|
79
87
|
def path
|
80
|
-
request_uri ? request_uri.split(
|
88
|
+
request_uri ? request_uri.split('?').first : ''
|
81
89
|
end
|
82
90
|
|
83
91
|
def port
|
84
|
-
env[
|
92
|
+
env['SERVER_PORT'].to_i
|
85
93
|
end
|
86
94
|
|
87
95
|
# Returns a string like ":8080" if the port is not 80 or 443 while on https.
|
88
96
|
def port_string
|
89
|
-
(protocol ==
|
97
|
+
(protocol == 'http://' && port == 80) || (protocol == 'https://' && port == 443) ? '' : ":#{port}"
|
90
98
|
end
|
91
99
|
|
92
100
|
def host_with_port
|
@@ -1,85 +1,83 @@
|
|
1
|
-
begin
|
2
|
-
require 'simplecc'
|
3
|
-
rescue LoadError
|
4
|
-
class Continuation
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
if
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
end
|
85
|
-
end
|
1
|
+
begin
|
2
|
+
require 'simplecc'
|
3
|
+
rescue LoadError
|
4
|
+
class Continuation; end # :nodoc: # for RDoc
|
5
|
+
def Continuation.create(*args, &block) # :nodoc:
|
6
|
+
cc = nil; result = callcc {|c| cc = c; block.call(cc) if block and args.empty?}
|
7
|
+
result ||= args
|
8
|
+
return *[cc, *result]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Binding; end # for RDoc
|
13
|
+
# This method returns the binding of the method that called your
|
14
|
+
# method. It will raise an Exception when you're not inside a method.
|
15
|
+
#
|
16
|
+
# It's used like this:
|
17
|
+
# def inc_counter(amount = 1)
|
18
|
+
# Binding.of_caller do |binding|
|
19
|
+
# # Create a lambda that will increase the variable 'counter'
|
20
|
+
# # in the caller of this method when called.
|
21
|
+
# inc = eval("lambda { |arg| counter += arg }", binding)
|
22
|
+
# # We can refer to amount from inside this block safely.
|
23
|
+
# inc.call(amount)
|
24
|
+
# end
|
25
|
+
# # No other statements can go here. Put them inside the block.
|
26
|
+
# end
|
27
|
+
# counter = 0
|
28
|
+
# 2.times { inc_counter }
|
29
|
+
# counter # => 2
|
30
|
+
#
|
31
|
+
# Binding.of_caller must be the last statement in the method.
|
32
|
+
# This means that you will have to put everything you want to
|
33
|
+
# do after the call to Binding.of_caller into the block of it.
|
34
|
+
# This should be no problem however, because Ruby has closures.
|
35
|
+
# If you don't do this an Exception will be raised. Because of
|
36
|
+
# the way that Binding.of_caller is implemented it has to be
|
37
|
+
# done this way.
|
38
|
+
def Binding.of_caller(&block)
|
39
|
+
old_critical = Thread.critical
|
40
|
+
Thread.critical = true
|
41
|
+
count = 0
|
42
|
+
cc, result, error, extra_data = Continuation.create(nil, nil)
|
43
|
+
error.call if error
|
44
|
+
|
45
|
+
tracer = lambda do |*args|
|
46
|
+
type, context, extra_data = args[0], args[4], args
|
47
|
+
if type == "return"
|
48
|
+
count += 1
|
49
|
+
# First this method and then calling one will return --
|
50
|
+
# the trace event of the second event gets the context
|
51
|
+
# of the method which called the method that called this
|
52
|
+
# method.
|
53
|
+
if count == 2
|
54
|
+
# It would be nice if we could restore the trace_func
|
55
|
+
# that was set before we swapped in our own one, but
|
56
|
+
# this is impossible without overloading set_trace_func
|
57
|
+
# in current Ruby.
|
58
|
+
set_trace_func(nil)
|
59
|
+
cc.call(eval("binding", context), nil, extra_data)
|
60
|
+
end
|
61
|
+
elsif type == "line" then
|
62
|
+
nil
|
63
|
+
elsif type == "c-return" and extra_data[3] == :set_trace_func then
|
64
|
+
nil
|
65
|
+
else
|
66
|
+
set_trace_func(nil)
|
67
|
+
error_msg = "Binding.of_caller used in non-method context or " +
|
68
|
+
"trailing statements of method using it aren't in the block."
|
69
|
+
cc.call(nil, lambda { raise(ArgumentError, error_msg) }, nil)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
unless result
|
74
|
+
set_trace_func(tracer)
|
75
|
+
return nil
|
76
|
+
else
|
77
|
+
Thread.critical = old_critical
|
78
|
+
case block.arity
|
79
|
+
when 1 then yield(result)
|
80
|
+
else yield(result, extra_data)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -16,11 +16,14 @@
|
|
16
16
|
# license please contact me.
|
17
17
|
|
18
18
|
require 'irb'
|
19
|
-
|
19
|
+
require File.dirname(__FILE__) + '/binding_of_caller'
|
20
20
|
require 'drb'
|
21
21
|
require 'drb/acl'
|
22
22
|
|
23
23
|
module Breakpoint
|
24
|
+
id = %q$Id: breakpoint.rb 41 2005-01-22 20:22:10Z flgr $
|
25
|
+
Version = id.split(" ")[2].to_i
|
26
|
+
|
24
27
|
extend self
|
25
28
|
|
26
29
|
# This will pop up an interactive ruby session at a
|
@@ -114,10 +117,10 @@ module Breakpoint
|
|
114
117
|
end
|
115
118
|
end
|
116
119
|
|
117
|
-
module CommandBundle
|
120
|
+
module CommandBundle
|
118
121
|
# Proxy to a Breakpoint client. Lets you directly execute code
|
119
122
|
# in the context of the client.
|
120
|
-
class Client
|
123
|
+
class Client
|
121
124
|
def initialize(eval_handler) # :nodoc:
|
122
125
|
@eval_handler = eval_handler
|
123
126
|
end
|
@@ -133,15 +136,23 @@ module Breakpoint
|
|
133
136
|
end
|
134
137
|
|
135
138
|
# Will execute the specified statement at the client.
|
136
|
-
def method_missing(method, *args)
|
137
|
-
if args.empty?
|
138
|
-
result = eval
|
139
|
+
def method_missing(method, *args, &block)
|
140
|
+
if args.empty? and not block
|
141
|
+
result = eval "#{method}"
|
139
142
|
else
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
143
|
+
# This is a bit ugly. The alternative would be using an
|
144
|
+
# eval context instead of an eval handler for executing
|
145
|
+
# the code at the client. The problem with that approach
|
146
|
+
# is that we would have to handle special expressions
|
147
|
+
# like "self", "nil" or constants ourself which is hard.
|
148
|
+
remote = eval %{
|
149
|
+
result = lambda { |block, *args| #{method}(*args, &block) }
|
150
|
+
def result.call_with_block(*args, &block)
|
151
|
+
call(block, *args)
|
152
|
+
end
|
153
|
+
result
|
154
|
+
}
|
155
|
+
remote.call_with_block(*args, &block)
|
145
156
|
end
|
146
157
|
|
147
158
|
return result
|
@@ -175,6 +186,7 @@ module Breakpoint
|
|
175
186
|
# client.File.open("temp.txt", "w") { |f| f.puts "Hello" }
|
176
187
|
def client()
|
177
188
|
if Breakpoint.use_drb? then
|
189
|
+
sleep(0.5) until Breakpoint.drb_service.eval_handler
|
178
190
|
Client.new(Breakpoint.drb_service.eval_handler)
|
179
191
|
else
|
180
192
|
Client.new(lambda { |code| eval(code, TOPLEVEL_BINDING) })
|
@@ -205,7 +217,7 @@ module Breakpoint
|
|
205
217
|
# These exceptions will be raised on failed asserts
|
206
218
|
# if Breakpoint.asserts_cause_exceptions is set to
|
207
219
|
# true.
|
208
|
-
class FailedAssertError < RuntimeError
|
220
|
+
class FailedAssertError < RuntimeError
|
209
221
|
end
|
210
222
|
|
211
223
|
# This asserts that the block evaluates to true.
|
@@ -279,7 +291,7 @@ module Breakpoint
|
|
279
291
|
@collision_handler.call
|
280
292
|
end
|
281
293
|
|
282
|
-
def ping
|
294
|
+
def ping() end
|
283
295
|
|
284
296
|
def add_breakpoint(context, message)
|
285
297
|
workspace = IRB::WorkSpace.new(context)
|
@@ -290,31 +302,7 @@ module Breakpoint
|
|
290
302
|
@handler.call(workspace, message)
|
291
303
|
end
|
292
304
|
|
293
|
-
|
294
|
-
@handler = block
|
295
|
-
end
|
296
|
-
|
297
|
-
def unregister_handler
|
298
|
-
@handler = nil
|
299
|
-
end
|
300
|
-
|
301
|
-
attr_reader :eval_handler
|
302
|
-
|
303
|
-
def register_eval_handler(&block)
|
304
|
-
@eval_handler = block
|
305
|
-
end
|
306
|
-
|
307
|
-
def unregister_eval_handler
|
308
|
-
@eval_handler = lambda { }
|
309
|
-
end
|
310
|
-
|
311
|
-
def register_collision_handler(&block)
|
312
|
-
@collision_handler = block
|
313
|
-
end
|
314
|
-
|
315
|
-
def unregister_collision_handler
|
316
|
-
@collision_handler = lambda { }
|
317
|
-
end
|
305
|
+
attr_accessor :handler, :eval_handler, :collision_handler
|
318
306
|
end
|
319
307
|
|
320
308
|
# Will run Breakpoint in DRb mode. This will spawn a server
|
@@ -359,7 +347,8 @@ module Breakpoint
|
|
359
347
|
#
|
360
348
|
# Detailed information about running DRb through firewalls is
|
361
349
|
# available at http://www.rubygarden.org/ruby?DrbTutorial
|
362
|
-
def activate_drb(uri = nil, allowed_hosts = ['localhost', '127.0.0.1', '::1'],
|
350
|
+
def activate_drb(uri = nil, allowed_hosts = ['localhost', '127.0.0.1', '::1'],
|
351
|
+
ignore_collisions = false)
|
363
352
|
|
364
353
|
return false if @use_drb
|
365
354
|
|
@@ -402,7 +391,7 @@ module Breakpoint
|
|
402
391
|
end
|
403
392
|
|
404
393
|
# Deactivates a running Breakpoint service.
|
405
|
-
def deactivate_drb
|
394
|
+
def deactivate_drb
|
406
395
|
@service.stop_service unless @service.nil?
|
407
396
|
@service = nil
|
408
397
|
@use_drb = false
|
@@ -411,14 +400,12 @@ module Breakpoint
|
|
411
400
|
|
412
401
|
# Returns true when Breakpoints are used over DRb.
|
413
402
|
# Breakpoint.activate_drb causes this to be true.
|
414
|
-
def use_drb?
|
403
|
+
def use_drb?
|
415
404
|
@use_drb == true
|
416
405
|
end
|
417
406
|
end
|
418
407
|
|
419
408
|
module IRB # :nodoc:
|
420
|
-
def IRB.parse_opts() end
|
421
|
-
|
422
409
|
class << self; remove_method :start; end
|
423
410
|
def self.start(ap_path = nil, main_context = nil, workspace = nil)
|
424
411
|
$0 = File::basename(ap_path, ".rb") if ap_path
|
@@ -442,7 +429,11 @@ module IRB # :nodoc:
|
|
442
429
|
@CONF[:MAIN_CONTEXT] = irb.context
|
443
430
|
|
444
431
|
old_sigint = trap("SIGINT") do
|
445
|
-
|
432
|
+
begin
|
433
|
+
irb.signal_handle
|
434
|
+
rescue RubyLex::TerminateLineInput
|
435
|
+
# ignored
|
436
|
+
end
|
446
437
|
end
|
447
438
|
|
448
439
|
catch(:IRB_EXIT) do
|
@@ -466,7 +457,7 @@ module IRB # :nodoc:
|
|
466
457
|
end
|
467
458
|
end
|
468
459
|
|
469
|
-
class Context
|
460
|
+
class Context
|
470
461
|
alias :old_evaluate :evaluate
|
471
462
|
def evaluate(line, line_no)
|
472
463
|
if line.chomp == "exit" then
|
@@ -477,7 +468,7 @@ module IRB # :nodoc:
|
|
477
468
|
end
|
478
469
|
end
|
479
470
|
|
480
|
-
class WorkSpace
|
471
|
+
class WorkSpace
|
481
472
|
alias :old_evaluate :evaluate
|
482
473
|
|
483
474
|
def evaluate(*args)
|
@@ -495,7 +486,7 @@ module IRB # :nodoc:
|
|
495
486
|
end
|
496
487
|
end
|
497
488
|
|
498
|
-
module InputCompletor
|
489
|
+
module InputCompletor
|
499
490
|
def self.eval(code, context, *more)
|
500
491
|
# Big hack, this assumes that InputCompletor
|
501
492
|
# will only call eval() when it wants code
|
@@ -506,9 +497,9 @@ module IRB # :nodoc:
|
|
506
497
|
end
|
507
498
|
|
508
499
|
module DRb # :nodoc:
|
509
|
-
class DRbObject
|
510
|
-
undef :inspect
|
511
|
-
undef :clone
|
500
|
+
class DRbObject
|
501
|
+
undef :inspect if method_defined?(:inspect)
|
502
|
+
undef :clone if method_defined?(:clone)
|
512
503
|
end
|
513
504
|
end
|
514
505
|
|
@@ -524,4 +515,4 @@ def assert(&block)
|
|
524
515
|
Binding.of_caller do |context|
|
525
516
|
Breakpoint.assert(context, &block)
|
526
517
|
end
|
527
|
-
end
|
518
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Object #:nodoc:
|
2
|
+
def remove_subclasses_of(superclass)
|
3
|
+
subclasses_of(superclass).each { |subclass| Object.send(:remove_const, subclass) rescue nil }
|
4
|
+
end
|
5
|
+
|
6
|
+
def subclasses_of(superclass)
|
7
|
+
subclasses = []
|
8
|
+
ObjectSpace.each_object(Class) do |k|
|
9
|
+
next if !k.ancestors.include?(superclass) || superclass == k || k.to_s.include?("::") || subclasses.include?(k.to_s)
|
10
|
+
subclasses << k.to_s
|
11
|
+
end
|
12
|
+
subclasses
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Class #:nodoc:
|
17
|
+
def remove_subclasses
|
18
|
+
Object.remove_subclasses_of(self)
|
19
|
+
end
|
20
|
+
|
21
|
+
def subclasses
|
22
|
+
Object.subclasses_of(self)
|
23
|
+
end
|
24
|
+
end
|
@@ -9,14 +9,19 @@ module Dependencies
|
|
9
9
|
@@mechanism = :load
|
10
10
|
mattr_accessor :mechanism
|
11
11
|
|
12
|
+
def load?
|
13
|
+
mechanism == :load
|
14
|
+
end
|
15
|
+
|
12
16
|
def depend_on(file_name, swallow_load_errors = false)
|
13
17
|
if !loaded.include?(file_name)
|
14
18
|
loaded << file_name
|
15
|
-
|
16
19
|
begin
|
17
20
|
require_or_load(file_name)
|
18
21
|
rescue LoadError
|
19
22
|
raise unless swallow_load_errors
|
23
|
+
rescue Object => e
|
24
|
+
raise ScriptError, "#{e.message}"
|
20
25
|
end
|
21
26
|
end
|
22
27
|
end
|
@@ -29,12 +34,16 @@ module Dependencies
|
|
29
34
|
self.loaded = [ ]
|
30
35
|
end
|
31
36
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
37
|
+
def require_or_load(file_name)
|
38
|
+
load? ? load("#{file_name}.rb") : require(file_name)
|
39
|
+
end
|
40
|
+
|
41
|
+
def remove_subclasses_for(*classes)
|
42
|
+
classes.each { |klass| klass.remove_subclasses }
|
43
|
+
end
|
36
44
|
end
|
37
45
|
|
46
|
+
Object.send(:define_method, :require_or_load) { |file_name| Dependencies.require_or_load(file_name) } unless Object.respond_to?(:require_or_load)
|
38
47
|
Object.send(:define_method, :require_dependency) { |file_name| Dependencies.depend_on(file_name) } unless Object.respond_to?(:require_dependency)
|
39
48
|
Object.send(:define_method, :require_association) { |file_name| Dependencies.associate_with(file_name) } unless Object.respond_to?(:require_association)
|
40
49
|
|
@@ -42,16 +51,12 @@ class Object #:nodoc:
|
|
42
51
|
class << self
|
43
52
|
# Use const_missing to autoload associations so we don't have to
|
44
53
|
# require_association when using single-table inheritance.
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
return Object.const_get(class_id) if Object.const_defined?(class_id)
|
52
|
-
rescue LoadError
|
53
|
-
pre_dependency_const_missing(class_id)
|
54
|
-
end
|
54
|
+
def const_missing(class_id)
|
55
|
+
begin
|
56
|
+
require_or_load(class_id.to_s.demodulize.underscore)
|
57
|
+
if Object.const_defined?(class_id) then return Object.const_get(class_id) else raise LoadError end
|
58
|
+
rescue LoadError
|
59
|
+
raise NameError, "uninitialized constant #{class_id}"
|
55
60
|
end
|
56
61
|
end
|
57
62
|
end
|
@@ -191,6 +191,23 @@ module ActionController #:nodoc:
|
|
191
191
|
headers['cookie'].inject({}) { |hash, cookie| hash[cookie.name] = cookie; hash }
|
192
192
|
end
|
193
193
|
|
194
|
+
# Returns binary content (downloadable file), converted to a String
|
195
|
+
def binary_content
|
196
|
+
raise "Response body is not a Proc: #{body.inspect}" unless body.kind_of?(Proc)
|
197
|
+
require 'stringio'
|
198
|
+
|
199
|
+
sio = StringIO.new
|
200
|
+
|
201
|
+
begin
|
202
|
+
$stdout = sio
|
203
|
+
body.call
|
204
|
+
ensure
|
205
|
+
$stdout = STDOUT
|
206
|
+
end
|
207
|
+
|
208
|
+
sio.rewind
|
209
|
+
sio.read
|
210
|
+
end
|
194
211
|
end
|
195
212
|
|
196
213
|
class TestSession #:nodoc:
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ActionController
|
2
2
|
# Rewrites urls for Base.redirect_to and Base.url_for in the controller.
|
3
3
|
class UrlRewriter #:nodoc:
|
4
|
-
VALID_OPTIONS = [:action, :action_prefix, :action_suffix, :module, :controller, :controller_prefix, :anchor, :params, :path_params, :id, :only_path, :overwrite_params, :host, :protocol ]
|
4
|
+
VALID_OPTIONS = [:action, :action_prefix, :action_suffix, :application_prefix, :module, :controller, :controller_prefix, :anchor, :params, :path_params, :id, :only_path, :overwrite_params, :host, :protocol ]
|
5
5
|
|
6
6
|
def initialize(request, controller, action)
|
7
7
|
@request, @controller, @action = request, controller, action
|
@@ -41,6 +41,7 @@ module ActionController
|
|
41
41
|
rewritten_url << (options[:protocol] || @request.protocol) unless options[:only_path]
|
42
42
|
rewritten_url << (options[:host] || @request.host_with_port) unless options[:only_path]
|
43
43
|
|
44
|
+
rewritten_url << options[:application_prefix] if options[:application_prefix]
|
44
45
|
rewritten_url << path
|
45
46
|
rewritten_url << build_query_string(new_parameters(options)) if options[:params] || options[:overwrite_params]
|
46
47
|
rewritten_url << "##{options[:anchor]}" if options[:anchor]
|
@@ -2,8 +2,8 @@ module ActionView
|
|
2
2
|
module Helpers
|
3
3
|
# See ActionController::Caching::Fragments for usage instructions.
|
4
4
|
module CacheHelper
|
5
|
-
def cache(
|
6
|
-
@controller.cache_erb_fragment(
|
5
|
+
def cache(name = {}, &block)
|
6
|
+
@controller.cache_erb_fragment(block, name)
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
@@ -137,6 +137,9 @@ module ActionView
|
|
137
137
|
def initialize(object_name, method_name, template_object, local_binding = nil)
|
138
138
|
@object_name, @method_name = object_name, method_name
|
139
139
|
@template_object, @local_binding = template_object, local_binding
|
140
|
+
if @object_name.sub!(/\[\]$/,"")
|
141
|
+
@auto_index = @template_object.instance_variable_get("@#{Regexp.last_match.pre_match}").id
|
142
|
+
end
|
140
143
|
end
|
141
144
|
|
142
145
|
def to_input_field_tag(field_type, options = {})
|
@@ -214,6 +217,9 @@ module ActionView
|
|
214
217
|
options['name'] = tag_name_with_index(options["index"]) unless options.has_key? "name"
|
215
218
|
options['id'] = tag_id_with_index(options["index"]) unless options.has_key? "id"
|
216
219
|
options.delete("index")
|
220
|
+
elsif @auto_index
|
221
|
+
options['name'] = tag_name_with_index(@auto_index) unless options.has_key? "name"
|
222
|
+
options['id'] = tag_id_with_index(@auto_index) unless options.has_key? "id"
|
217
223
|
else
|
218
224
|
options['name'] = tag_name unless options.has_key? "name"
|
219
225
|
options['id'] = tag_id unless options.has_key? "id"
|
@@ -91,8 +91,35 @@ module ActionView
|
|
91
91
|
|
92
92
|
# Creates a link tag for starting an email to the specified <tt>email_address</tt>, which is also used as the name of the
|
93
93
|
# link unless +name+ is specified. Additional HTML options, such as class or id, can be passed in the <tt>html_options</tt> hash.
|
94
|
+
#
|
95
|
+
# You can also make it difficult for spiders to harvest email address by obfuscating them.
|
96
|
+
# Examples:
|
97
|
+
# * mail_to "me@domain.com", "My email", :encode => "javascript"
|
98
|
+
# => <script type="text/javascript" language="javascript">eval(unescape('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'))</script>
|
99
|
+
# * mail_to "me@domain.com", "My email", :encode => "hex"
|
100
|
+
# => <a href="mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d">My email</a>
|
94
101
|
def mail_to(email_address, name = nil, html_options = {})
|
95
|
-
|
102
|
+
encode = html_options[:encode]
|
103
|
+
html_options.delete(:encode)
|
104
|
+
string = ''
|
105
|
+
if encode == 'javascript'
|
106
|
+
tmp = "document.write('#{content_tag("a", name || email_address, html_options.merge({ "href" => "mailto:"+email_address.to_s }))}');"
|
107
|
+
for i in 0...tmp.length
|
108
|
+
string << sprintf("%%%x",tmp[i])
|
109
|
+
end
|
110
|
+
"<script type=\"text/javascript\" language=\"javascript\">eval(unescape('#{string}'))</script>"
|
111
|
+
elsif encode == 'hex'
|
112
|
+
for i in 0...email_address.length
|
113
|
+
if email_address[i,1] =~ /\w/
|
114
|
+
string << sprintf("%%%x",email_address[i])
|
115
|
+
else
|
116
|
+
string << email_address[i,1]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
content_tag "a", name || email_address, html_options.merge({ "href" => "mailto:#{string}" })
|
120
|
+
else
|
121
|
+
content_tag "a", name || email_address, html_options.merge({ "href" => "mailto:#{email_address}" })
|
122
|
+
end
|
96
123
|
end
|
97
124
|
|
98
125
|
private
|
@@ -221,7 +221,7 @@ module Builder
|
|
221
221
|
# For example:
|
222
222
|
#
|
223
223
|
# xml.instruct!
|
224
|
-
# #=> <?xml encoding="UTF-8"
|
224
|
+
# #=> <?xml version="1.0" encoding="UTF-8"?>
|
225
225
|
# xml.instruct! :aaa, :bbb=>"ccc"
|
226
226
|
# #=> <?aaa bbb="ccc"?>
|
227
227
|
#
|
@@ -231,7 +231,12 @@ module Builder
|
|
231
231
|
a = { :version=>"1.0", :encoding=>"UTF-8" }
|
232
232
|
attrs = a.merge attrs
|
233
233
|
end
|
234
|
-
_special(
|
234
|
+
_special(
|
235
|
+
"<?#{directive_tag}",
|
236
|
+
"?>",
|
237
|
+
nil,
|
238
|
+
attrs,
|
239
|
+
[:version, :encoding, :standalone])
|
235
240
|
end
|
236
241
|
|
237
242
|
private
|
@@ -245,11 +250,11 @@ module Builder
|
|
245
250
|
end
|
246
251
|
|
247
252
|
# Insert special instruction.
|
248
|
-
def _special(open, close, data=nil, attrs=nil)
|
253
|
+
def _special(open, close, data=nil, attrs=nil, order=[])
|
249
254
|
_indent
|
250
255
|
@target << open
|
251
256
|
@target << data if data
|
252
|
-
_insert_attributes(attrs) if attrs
|
257
|
+
_insert_attributes(attrs, order) if attrs
|
253
258
|
@target << close
|
254
259
|
_newline
|
255
260
|
end
|
@@ -269,10 +274,14 @@ module Builder
|
|
269
274
|
end
|
270
275
|
|
271
276
|
# Insert the attributes (given in the hash).
|
272
|
-
def _insert_attributes(attrs)
|
277
|
+
def _insert_attributes(attrs, order=[])
|
273
278
|
return if attrs.nil?
|
279
|
+
order.each do |k|
|
280
|
+
v = attrs[k]
|
281
|
+
@target << %{ #{k}="#{v}"} if v
|
282
|
+
end
|
274
283
|
attrs.each do |k, v|
|
275
|
-
@target << %{ #{k}="#{v}"}
|
284
|
+
@target << %{ #{k}="#{v}"} unless order.member?(k)
|
276
285
|
end
|
277
286
|
end
|
278
287
|
|
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 = '1.
|
11
|
+
PKG_VERSION = '1.4.0' + PKG_BUILD
|
12
12
|
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
13
13
|
|
14
14
|
desc "Default Task"
|
@@ -14,6 +14,20 @@ class FilterTest < Test::Unit::TestCase
|
|
14
14
|
@ran_filter << "ensure_login"
|
15
15
|
end
|
16
16
|
end
|
17
|
+
|
18
|
+
class RenderingController < ActionController::Base
|
19
|
+
before_filter :render_something_else
|
20
|
+
|
21
|
+
def show
|
22
|
+
@ran_action = true
|
23
|
+
render_text "ran action"
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
def render_something_else
|
28
|
+
render_text "something else"
|
29
|
+
end
|
30
|
+
end
|
17
31
|
|
18
32
|
class ConditionalFilterController < ActionController::Base
|
19
33
|
def show
|
@@ -264,6 +278,12 @@ class FilterTest < Test::Unit::TestCase
|
|
264
278
|
" after appended aroundfilter after aroundfilter after procfilter ",
|
265
279
|
MixedFilterController.execution_log
|
266
280
|
end
|
281
|
+
|
282
|
+
def test_rendering_breaks_filtering_chain
|
283
|
+
response = test_process(RenderingController)
|
284
|
+
assert_equal "something else", response.body
|
285
|
+
assert !response.template.assigns["ran_action"]
|
286
|
+
end
|
267
287
|
|
268
288
|
private
|
269
289
|
def test_process(controller, action = "show")
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'cgi'
|
3
|
+
require 'stringio'
|
4
|
+
require File.dirname(__FILE__) + '/../../lib/action_controller/cgi_ext/raw_post_data_fix'
|
5
|
+
|
6
|
+
class RawPostDataTest < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
ENV['REQUEST_METHOD'] = 'POST'
|
9
|
+
ENV['CONTENT_TYPE'] = ''
|
10
|
+
ENV['CONTENT_LENGTH'] = '0'
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_raw_post_data
|
14
|
+
process_raw "action=create_customer&full_name=David%20Heinemeier%20Hansson&customerId=1"
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
def process_raw(query_string)
|
19
|
+
old_stdin = $stdin
|
20
|
+
begin
|
21
|
+
$stdin = StringIO.new(query_string.dup)
|
22
|
+
ENV['CONTENT_LENGTH'] = $stdin.size.to_s
|
23
|
+
CGI.new
|
24
|
+
assert_not_nil ENV['RAW_POST_DATA']
|
25
|
+
assert ENV['RAW_POST_DATA'].frozen?
|
26
|
+
assert_equal query_string, ENV['RAW_POST_DATA']
|
27
|
+
ensure
|
28
|
+
$stdin = old_stdin
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/test/controller/url_test.rb
CHANGED
@@ -453,4 +453,25 @@ class UrlTest < Test::Unit::TestCase
|
|
453
453
|
url.rewrite({ :controller => "msg", :action_prefix => "allous", :action => "new" })
|
454
454
|
)
|
455
455
|
end
|
456
|
+
|
457
|
+
def test_clean_application_prefix
|
458
|
+
assert_equal "http://www.singlefile.com/namespace/library/books/ISBN/0743536703/show",
|
459
|
+
@library_url.rewrite(:application_prefix => "/namespace")
|
460
|
+
end
|
461
|
+
|
462
|
+
def test_clean_application_prefix_with_controller_prefix
|
463
|
+
assert_equal "http://www.singlefile.com/namespace/shop/",
|
464
|
+
@library_url.rewrite(:application_prefix => "/namespace",
|
465
|
+
:controller_prefix => "shop" )
|
466
|
+
end
|
467
|
+
|
468
|
+
def test_blank_application_prefix
|
469
|
+
assert_equal "http://www.singlefile.com/library/books/ISBN/0743536703/show",
|
470
|
+
@library_url.rewrite(:application_prefix => "")
|
471
|
+
end
|
472
|
+
|
473
|
+
def test_nil_application_prefix
|
474
|
+
assert_equal "http://www.singlefile.com/library/books/ISBN/0743536703/show",
|
475
|
+
@library_url.rewrite(:application_prefix => nil)
|
476
|
+
end
|
456
477
|
end
|
@@ -18,6 +18,8 @@ class FormHelperTest < Test::Unit::TestCase
|
|
18
18
|
@post = Post.new
|
19
19
|
def @post.errors() Class.new{ def on(field) field == "author_name" end }.new end
|
20
20
|
|
21
|
+
def @post.id; 123; end
|
22
|
+
|
21
23
|
@post.title = "Hello World"
|
22
24
|
@post.author_name = ""
|
23
25
|
@post.body = "Back to the hill and over it again!"
|
@@ -136,4 +138,28 @@ class FormHelperTest < Test::Unit::TestCase
|
|
136
138
|
check_box("post", "secret", "id" => "i mean it")
|
137
139
|
)
|
138
140
|
end
|
141
|
+
|
142
|
+
def test_auto_index
|
143
|
+
pid = @post.id
|
144
|
+
assert_equal(
|
145
|
+
"<input id=\"post_#{pid}_title\" name=\"post[#{pid}][title]\" size=\"30\" type=\"text\" value=\"Hello World\" />", text_field("post[]","title")
|
146
|
+
)
|
147
|
+
assert_equal(
|
148
|
+
"<textarea cols=\"40\" id=\"post_#{pid}_body\" name=\"post[#{pid}][body]\" rows=\"20\" wrap=\"virtual\">Back to the hill and over it again!</textarea>",
|
149
|
+
text_area("post[]", "body")
|
150
|
+
)
|
151
|
+
assert_equal(
|
152
|
+
"<input checked=\"checked\" id=\"post_#{pid}_secret\" name=\"post[#{pid}][secret]\" type=\"checkbox\" value=\"1\" /><input name=\"post[#{pid}][secret]\" type=\"hidden\" value=\"0\" />",
|
153
|
+
check_box("post[]", "secret")
|
154
|
+
)
|
155
|
+
assert_equal(
|
156
|
+
"<input checked=\"checked\" id=\"post_#{pid}_title\" name=\"post[#{pid}][title]\" size=\"30\" type=\"radio\" value=\"Hello World\" />",
|
157
|
+
radio_button("post[]", "title", "Hello World")
|
158
|
+
)
|
159
|
+
assert_equal("<input id=\"post_#{pid}_title\" name=\"post[#{pid}][title]\" size=\"30\" type=\"radio\" value=\"Goodbye World\" />",
|
160
|
+
radio_button("post[]", "title", "Goodbye World")
|
161
|
+
)
|
162
|
+
|
163
|
+
end
|
164
|
+
|
139
165
|
end
|
@@ -14,5 +14,17 @@ class TagHelperTest < Test::Unit::TestCase
|
|
14
14
|
assert_equal "<a href=\"create\">Create</a>", content_tag("a", "Create", "href" => "create")
|
15
15
|
end
|
16
16
|
|
17
|
+
def test_mail_to_with_javascript
|
18
|
+
assert_equal "<script type=\"text/javascript\" language=\"javascript\">eval(unescape('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", "My email", :encode => "javascript")
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_mail_to_with_hex
|
22
|
+
assert_equal "<a href=\"mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d\">My email</a>", mail_to("me@domain.com", "My email", :encode => "hex")
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_mail_to
|
26
|
+
assert_equal "<a href=\"mailto:me@domain.com\">My email</a>", mail_to("me@domain.com", "My email")
|
27
|
+
end
|
28
|
+
|
17
29
|
# FIXME: Test form tag
|
18
30
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: actionpack
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.
|
7
|
-
date: 2005-01-
|
6
|
+
version: 1.4.0
|
7
|
+
date: 2005-01-25
|
8
8
|
summary: Web-flow and rendering framework putting the VC in MVC.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -67,6 +67,7 @@ files:
|
|
67
67
|
- lib/action_controller/cgi_ext/cgi_ext.rb
|
68
68
|
- lib/action_controller/cgi_ext/cgi_methods.rb
|
69
69
|
- lib/action_controller/cgi_ext/cookie_performance_fix.rb
|
70
|
+
- lib/action_controller/cgi_ext/raw_post_data_fix.rb
|
70
71
|
- lib/action_controller/session/active_record_store.rb
|
71
72
|
- lib/action_controller/session/drb_server.rb
|
72
73
|
- lib/action_controller/session/drb_store.rb
|
@@ -86,6 +87,7 @@ files:
|
|
86
87
|
- lib/action_controller/support/core_ext/hash.rb
|
87
88
|
- lib/action_controller/support/core_ext/numeric
|
88
89
|
- lib/action_controller/support/core_ext/numeric.rb
|
90
|
+
- lib/action_controller/support/core_ext/object_and_class.rb
|
89
91
|
- lib/action_controller/support/core_ext/string
|
90
92
|
- lib/action_controller/support/core_ext/string.rb
|
91
93
|
- lib/action_controller/support/core_ext/hash/keys.rb
|
@@ -137,6 +139,7 @@ files:
|
|
137
139
|
- test/controller/flash_test.rb
|
138
140
|
- test/controller/helper_test.rb
|
139
141
|
- test/controller/layout_test.rb
|
142
|
+
- test/controller/raw_post_test.rb
|
140
143
|
- test/controller/redirect_test.rb
|
141
144
|
- test/controller/render_test.rb
|
142
145
|
- test/controller/request_test.rb
|