actionpack 1.12.5 → 1.13.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 +517 -15
- data/MIT-LICENSE +1 -1
- data/README +18 -20
- data/Rakefile +7 -4
- data/examples/address_book_controller.rb +3 -3
- data/examples/blog_controller.cgi +3 -3
- data/examples/debate_controller.cgi +5 -5
- data/lib/action_controller.rb +2 -2
- data/lib/action_controller/assertions.rb +73 -311
- data/lib/action_controller/{deprecated_assertions.rb → assertions/deprecated_assertions.rb} +32 -8
- data/lib/action_controller/assertions/dom_assertions.rb +25 -0
- data/lib/action_controller/assertions/model_assertions.rb +12 -0
- data/lib/action_controller/assertions/response_assertions.rb +140 -0
- data/lib/action_controller/assertions/routing_assertions.rb +82 -0
- data/lib/action_controller/assertions/selector_assertions.rb +571 -0
- data/lib/action_controller/assertions/tag_assertions.rb +117 -0
- data/lib/action_controller/base.rb +334 -163
- data/lib/action_controller/benchmarking.rb +3 -6
- data/lib/action_controller/caching.rb +83 -22
- data/lib/action_controller/cgi_ext/cgi_ext.rb +0 -7
- data/lib/action_controller/cgi_ext/cgi_methods.rb +167 -173
- data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +43 -22
- data/lib/action_controller/cgi_process.rb +50 -27
- data/lib/action_controller/components.rb +21 -25
- data/lib/action_controller/cookies.rb +10 -9
- data/lib/action_controller/{dependencies.rb → deprecated_dependencies.rb} +9 -27
- data/lib/action_controller/filters.rb +448 -225
- data/lib/action_controller/flash.rb +24 -20
- data/lib/action_controller/helpers.rb +2 -5
- data/lib/action_controller/integration.rb +40 -16
- data/lib/action_controller/layout.rb +11 -8
- data/lib/action_controller/macros/auto_complete.rb +3 -2
- data/lib/action_controller/macros/in_place_editing.rb +3 -2
- data/lib/action_controller/mime_responds.rb +41 -29
- data/lib/action_controller/mime_type.rb +68 -10
- data/lib/action_controller/pagination.rb +4 -3
- data/lib/action_controller/request.rb +22 -14
- data/lib/action_controller/rescue.rb +25 -22
- data/lib/action_controller/resources.rb +302 -0
- data/lib/action_controller/response.rb +20 -2
- data/lib/action_controller/response.rb.rej +17 -0
- data/lib/action_controller/routing.rb +1165 -567
- data/lib/action_controller/scaffolding.rb +30 -31
- data/lib/action_controller/session/active_record_store.rb +2 -0
- data/lib/action_controller/session/drb_store.rb +4 -0
- data/lib/action_controller/session/mem_cache_store.rb +4 -0
- data/lib/action_controller/session_management.rb +6 -9
- data/lib/action_controller/status_codes.rb +89 -0
- data/lib/action_controller/streaming.rb +6 -15
- data/lib/action_controller/templates/rescues/_request_and_response.rhtml +5 -5
- data/lib/action_controller/templates/rescues/diagnostics.rhtml +2 -2
- data/lib/action_controller/templates/rescues/routing_error.rhtml +4 -4
- data/lib/action_controller/templates/rescues/template_error.rhtml +1 -1
- data/lib/action_controller/templates/scaffolds/list.rhtml +1 -1
- data/lib/action_controller/test_process.rb +52 -30
- data/lib/action_controller/url_rewriter.rb +63 -29
- data/lib/action_controller/vendor/html-scanner/html/document.rb +1 -0
- data/lib/action_controller/vendor/html-scanner/html/node.rb +3 -4
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +822 -0
- data/lib/action_controller/verification.rb +22 -11
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/version.rb +2 -2
- data/lib/action_view.rb +1 -1
- data/lib/action_view/base.rb +46 -43
- data/lib/action_view/compiled_templates.rb +1 -1
- data/lib/action_view/helpers/active_record_helper.rb +54 -17
- data/lib/action_view/helpers/asset_tag_helper.rb +97 -46
- data/lib/action_view/helpers/capture_helper.rb +1 -1
- data/lib/action_view/helpers/date_helper.rb +258 -136
- data/lib/action_view/helpers/debug_helper.rb +1 -1
- data/lib/action_view/helpers/deprecated_helper.rb +34 -0
- data/lib/action_view/helpers/form_helper.rb +75 -35
- data/lib/action_view/helpers/form_options_helper.rb +7 -5
- data/lib/action_view/helpers/form_tag_helper.rb +44 -6
- data/lib/action_view/helpers/java_script_macros_helper.rb +59 -46
- data/lib/action_view/helpers/javascript_helper.rb +71 -10
- data/lib/action_view/helpers/javascripts/controls.js +41 -23
- data/lib/action_view/helpers/javascripts/dragdrop.js +105 -76
- data/lib/action_view/helpers/javascripts/effects.js +293 -163
- data/lib/action_view/helpers/javascripts/prototype.js +897 -389
- data/lib/action_view/helpers/javascripts/prototype.js.rej +561 -0
- data/lib/action_view/helpers/number_helper.rb +111 -65
- data/lib/action_view/helpers/prototype_helper.rb +84 -109
- data/lib/action_view/helpers/scriptaculous_helper.rb +5 -0
- data/lib/action_view/helpers/tag_helper.rb +69 -16
- data/lib/action_view/helpers/text_helper.rb +149 -112
- data/lib/action_view/helpers/url_helper.rb +200 -107
- data/lib/action_view/template_error.rb +66 -42
- data/test/abstract_unit.rb +4 -2
- data/test/active_record_unit.rb +84 -56
- data/test/activerecord/active_record_assertions_test.rb +26 -18
- data/test/activerecord/active_record_store_test.rb +4 -36
- data/test/activerecord/pagination_test.rb +1 -6
- data/test/controller/action_pack_assertions_test.rb +230 -113
- data/test/controller/addresses_render_test.rb +2 -6
- data/test/controller/assert_select_test.rb +576 -0
- data/test/controller/base_test.rb +73 -3
- data/test/controller/caching_test.rb +228 -0
- data/test/controller/capture_test.rb +12 -10
- data/test/controller/cgi_test.rb +89 -12
- data/test/controller/components_test.rb +24 -2
- data/test/controller/content_type_test.rb +139 -0
- data/test/controller/controller_fixtures/app/controllers/admin/user_controller.rb +0 -0
- data/test/controller/controller_fixtures/app/controllers/user_controller.rb +0 -0
- data/test/controller/controller_fixtures/vendor/plugins/bad_plugin/lib/plugin_controller.rb +0 -0
- data/test/controller/cookie_test.rb +33 -25
- data/test/controller/deprecated_instance_variables_test.rb +48 -0
- data/test/controller/deprecation/deprecated_base_methods_test.rb +60 -0
- data/test/controller/fake_controllers.rb +0 -1
- data/test/controller/filters_test.rb +301 -16
- data/test/controller/flash_test.rb +19 -2
- data/test/controller/helper_test.rb +2 -2
- data/test/controller/integration_test.rb +154 -0
- data/test/controller/layout_test.rb +115 -1
- data/test/controller/mime_responds_test.rb +94 -0
- data/test/controller/mime_type_test.rb +9 -0
- data/test/controller/new_render_test.rb +161 -11
- data/test/controller/raw_post_test.rb +52 -15
- data/test/controller/redirect_test.rb +27 -14
- data/test/controller/render_test.rb +76 -29
- data/test/controller/request_test.rb +55 -4
- data/test/controller/resources_test.rb +274 -0
- data/test/controller/routing_test.rb +1533 -824
- data/test/controller/selector_test.rb +628 -0
- data/test/controller/send_file_test.rb +9 -1
- data/test/controller/session_management_test.rb +51 -0
- data/test/controller/test_test.rb +113 -29
- data/test/controller/url_rewriter_test.rb +86 -17
- data/test/controller/verification_test.rb +19 -17
- data/test/controller/webservice_test.rb +0 -7
- data/test/fixtures/content_type/render_default_content_types_for_respond_to.rhtml +1 -0
- data/test/fixtures/content_type/render_default_for_rhtml.rhtml +1 -0
- data/test/fixtures/content_type/render_default_for_rjs.rjs +1 -0
- data/test/fixtures/content_type/render_default_for_rxml.rxml +1 -0
- data/test/fixtures/deprecated_instance_variables/_cookies_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_cookies_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_flash_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_flash_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_headers_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_headers_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_params_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_params_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_request_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_request_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_response_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_response_method.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_session_ivar.rhtml +1 -0
- data/test/fixtures/deprecated_instance_variables/_session_method.rhtml +1 -0
- data/test/fixtures/multipart/binary_file +0 -0
- data/test/fixtures/public/javascripts/application.js +1 -0
- data/test/fixtures/test/_hello.rxml +1 -0
- data/test/fixtures/test/hello_world_container.rxml +3 -0
- data/test/fixtures/topic.rb +2 -2
- data/test/template/active_record_helper_test.rb +83 -12
- data/test/template/asset_tag_helper_test.rb +75 -95
- data/test/template/compiled_templates_test.rb +1 -0
- data/test/template/date_helper_test.rb +873 -181
- data/test/template/deprecated_helper_test.rb +36 -0
- data/test/template/deprecated_instance_variables_test.rb +43 -0
- data/test/template/form_helper_test.rb +77 -1
- data/test/template/form_options_helper_test.rb +4 -0
- data/test/template/form_tag_helper_test.rb +66 -2
- data/test/template/java_script_macros_helper_test.rb +4 -1
- data/test/template/javascript_helper_test.rb +29 -0
- data/test/template/number_helper_test.rb +63 -27
- data/test/template/prototype_helper_test.rb +77 -34
- data/test/template/tag_helper_test.rb +34 -6
- data/test/template/text_helper_test.rb +69 -34
- data/test/template/url_helper_test.rb +168 -16
- data/test/testing_sandbox.rb +7 -22
- metadata +66 -20
- data/filler.txt +0 -50
- data/lib/action_controller/code_generation.rb +0 -235
- data/lib/action_controller/vendor/xml_simple.rb +0 -1019
- data/test/controller/caching_filestore.rb +0 -74
- data/test/fixtures/application_root/app/controllers/a_class_that_contains_a_controller/poorly_placed_controller.rb +0 -7
- data/test/fixtures/application_root/app/controllers/module_that_holds_controllers/nested_controller.rb +0 -3
- data/test/fixtures/application_root/app/models/a_class_that_contains_a_controller.rb +0 -7
- data/test/fixtures/dont_load.rb +0 -3
@@ -1,22 +1,21 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/javascript_helper'
|
2
2
|
|
3
3
|
module ActionView
|
4
|
-
module Helpers
|
5
|
-
# Provides a set of methods for making easy links and getting urls that
|
6
|
-
#
|
7
|
-
#
|
8
|
-
# redirection in redirect_to.
|
4
|
+
module Helpers #:nodoc:
|
5
|
+
# Provides a set of methods for making easy links and getting urls that
|
6
|
+
# depend on the controller and action. This means that you can use the
|
7
|
+
# same format for links in the views that you do in the controller.
|
9
8
|
module UrlHelper
|
10
9
|
include JavaScriptHelper
|
11
10
|
|
12
|
-
# Returns the URL for the set of +options+ provided. This takes the
|
13
|
-
# as url_for. For a list, see the
|
14
|
-
# Note that it'll
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
11
|
+
# Returns the URL for the set of +options+ provided. This takes the
|
12
|
+
# same options as url_for in action controller. For a list, see the
|
13
|
+
# documentation for ActionController::Base#url_for. Note that it'll
|
14
|
+
# set :only_path => true so you'll get the relative /controller/action
|
15
|
+
# instead of the fully qualified http://example.com/controller/action.
|
16
|
+
#
|
17
|
+
# When called from a view, url_for returns an HTML escaped url. If you
|
18
|
+
# need an unescaped url, pass :escape => false in the +options+.
|
20
19
|
def url_for(options = {}, *parameters_for_method_reference)
|
21
20
|
if options.kind_of? Hash
|
22
21
|
options = { :only_path => true }.update(options.symbolize_keys)
|
@@ -24,30 +23,46 @@ module ActionView
|
|
24
23
|
else
|
25
24
|
escape = true
|
26
25
|
end
|
26
|
+
|
27
27
|
url = @controller.send(:url_for, options, *parameters_for_method_reference)
|
28
28
|
escape ? html_escape(url) : url
|
29
29
|
end
|
30
30
|
|
31
|
-
# Creates a link tag of the given +name+ using
|
32
|
-
#
|
33
|
-
#
|
31
|
+
# Creates a link tag of the given +name+ using a URL created by the set
|
32
|
+
# of +options+. See the valid options in the documentation for
|
33
|
+
# ActionController::Base#url_for. It's also possible to pass a string instead
|
34
|
+
# of an options hash to get a link tag that uses the value of the string as the
|
35
|
+
# href for the link. If nil is passed as a name, the link itself will become
|
36
|
+
# the name.
|
34
37
|
#
|
35
|
-
# The html_options
|
36
|
-
#
|
38
|
+
# The +html_options+ will accept a hash of html attributes for the link tag.
|
39
|
+
# It also accepts 3 modifiers that specialize the link behavior.
|
37
40
|
#
|
38
|
-
#
|
39
|
-
#
|
41
|
+
# * <tt>:confirm => 'question?'</tt>: This will add a JavaScript confirm
|
42
|
+
# prompt with the question specified. If the user accepts, the link is
|
43
|
+
# processed normally, otherwise no action is taken.
|
44
|
+
# * <tt>:popup => true || array of window options</tt>: This will force the
|
45
|
+
# link to open in a popup window. By passing true, a default browser window
|
46
|
+
# will be opened with the URL. You can also specify an array of options
|
47
|
+
# that are passed-thru to JavaScripts window.open method.
|
48
|
+
# * <tt>:method => symbol of HTTP verb</tt>: This modifier will dynamically
|
49
|
+
# create an HTML form and immediately submit the form for processing using
|
50
|
+
# the HTTP verb specified. Useful for having links perform a POST operation
|
51
|
+
# in dangerous actions like deleting a record (which search bots can follow
|
52
|
+
# while spidering your site). Supported verbs are :post, :delete and :put.
|
53
|
+
# Note that if the user has JavaScript disabled, the request will fall back
|
54
|
+
# to using GET. If you are relying on the POST behavior, your should check
|
55
|
+
# for it in your controllers action by using the request objects methods
|
56
|
+
# for post?, delete? or put?.
|
40
57
|
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
# passing :post as true. Note, it's not possible to use POST requests and popup targets at the same time (an exception will be thrown).
|
58
|
+
# You can mix and match the +html_options+ with the exception of
|
59
|
+
# :popup and :method which will raise an ActionView::ActionViewError
|
60
|
+
# exception.
|
45
61
|
#
|
46
|
-
#
|
47
|
-
# link_to "Delete this page", { :action => "destroy", :id => @page.id }, :confirm => "Are you sure?"
|
62
|
+
# link_to "Visit Other Site", "http://www.rubyonrails.org/", :confirm => "Are you sure?"
|
48
63
|
# link_to "Help", { :action => "help" }, :popup => true
|
49
|
-
# link_to "
|
50
|
-
# link_to "
|
64
|
+
# link_to "View Image", { :action => "view" }, :popup => ['new_window_name', 'height=300,width=600']
|
65
|
+
# link_to "Delete Image", { :action => "delete", :id => @image.id }, :confirm => "Are you sure?", :method => :delete
|
51
66
|
def link_to(name, options = {}, html_options = nil, *parameters_for_method_reference)
|
52
67
|
if html_options
|
53
68
|
html_options = html_options.stringify_keys
|
@@ -56,76 +71,77 @@ module ActionView
|
|
56
71
|
else
|
57
72
|
tag_options = nil
|
58
73
|
end
|
74
|
+
|
59
75
|
url = options.is_a?(String) ? options : self.url_for(options, *parameters_for_method_reference)
|
60
76
|
"<a href=\"#{url}\"#{tag_options}>#{name || url}</a>"
|
61
77
|
end
|
62
78
|
|
63
|
-
# Generates a form containing a
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
79
|
+
# Generates a form containing a single button that submits to the URL created
|
80
|
+
# by the set of +options+. This is the safest method to ensure links that
|
81
|
+
# cause changes to your data are not triggered by search bots or accelerators.
|
82
|
+
# If the HTML button does not work with your layout, you can also consider
|
83
|
+
# using the link_to method with the <tt>:method</tt> modifier as described in
|
84
|
+
# the link_to documentation.
|
67
85
|
#
|
68
|
-
# The
|
69
|
-
#
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
# disabled. The generated form element is given the class
|
76
|
-
# 'button-to', to which you can attach CSS styles for display
|
77
|
-
# purposes.
|
78
|
-
#
|
79
|
-
# Example 1:
|
86
|
+
# The generated FORM element has a class name of <tt>button-to</tt>
|
87
|
+
# to allow styling of the form itself and its children. You can control
|
88
|
+
# the form submission and input element behavior using +html_options+.
|
89
|
+
# This method accepts the <tt>:method</tt> and <tt>:confirm</tt> modifiers
|
90
|
+
# described in the link_to documentation. If no <tt>:method</tt> modifier
|
91
|
+
# is given, it will default to performing a POST operation. You can also
|
92
|
+
# disable the button by passing <tt>:disabled => true</tt> in +html_options+.
|
80
93
|
#
|
81
|
-
#
|
82
|
-
# button_to "Edit", :action => 'edit', :id => 3
|
94
|
+
# button_to "New", :action => "new"
|
83
95
|
#
|
84
|
-
# Generates the following HTML
|
96
|
+
# Generates the following HTML:
|
85
97
|
#
|
86
|
-
# <form method="post" action="/
|
87
|
-
# <div><input value="
|
98
|
+
# <form method="post" action="/controller/new" class="button-to">
|
99
|
+
# <div><input value="New" type="submit" /></div>
|
88
100
|
# </form>
|
89
101
|
#
|
90
|
-
#
|
102
|
+
# If you are using RESTful routes, you can pass the <tt>:method</tt>
|
103
|
+
# to change the HTTP verb used to submit the form.
|
91
104
|
#
|
92
|
-
# button_to "
|
93
|
-
# :confirm => "Are you sure?"
|
105
|
+
# button_to "Delete Image", { :action => "delete", :id => @image.id },
|
106
|
+
# :confirm => "Are you sure?", :method => :delete
|
94
107
|
#
|
95
|
-
#
|
108
|
+
# Which generates the following HTML:
|
96
109
|
#
|
97
|
-
# <form method="post" action="/
|
98
|
-
# <div
|
99
|
-
#
|
110
|
+
# <form method="post" action="/images/delete/1" class="button-to">
|
111
|
+
# <div>
|
112
|
+
# <input type="hidden" name="_method" value="delete" />
|
113
|
+
# <input onclick="return confirm('Are you sure?');"
|
114
|
+
# value="Delete" type="submit" />
|
100
115
|
# </div>
|
101
116
|
# </form>
|
102
|
-
|
103
|
-
|
104
|
-
# Forms are "block" content, which means that you should not try to
|
105
|
-
# insert them into your HTML where only inline content is expected.
|
106
|
-
# For example, you can legally insert a form inside of a +div+ or
|
107
|
-
# +td+ element or in between +p+ elements, but not in the middle of
|
108
|
-
# a run of text, nor can you place a form within another form.
|
109
|
-
# (Bottom line: Always validate your HTML before going public.)
|
110
|
-
def button_to(name, options = {}, html_options = nil)
|
111
|
-
html_options = (html_options || {}).stringify_keys
|
117
|
+
def button_to(name, options = {}, html_options = {})
|
118
|
+
html_options = html_options.stringify_keys
|
112
119
|
convert_boolean_attributes!(html_options, %w( disabled ))
|
113
|
-
|
120
|
+
|
121
|
+
method_tag = ''
|
122
|
+
if (method = html_options.delete('method')) && %w{put delete}.include?(method.to_s)
|
123
|
+
method_tag = tag('input', :type => 'hidden', :name => '_method', :value => method.to_s)
|
124
|
+
end
|
125
|
+
|
126
|
+
form_method = method.to_s == 'get' ? 'get' : 'post'
|
127
|
+
|
114
128
|
if confirm = html_options.delete("confirm")
|
115
129
|
html_options["onclick"] = "return #{confirm_javascript_function(confirm)};"
|
116
130
|
end
|
117
|
-
|
118
|
-
url = options.is_a?(String) ? options : url_for(options)
|
131
|
+
|
132
|
+
url = options.is_a?(String) ? options : self.url_for(options)
|
119
133
|
name ||= url
|
120
|
-
|
121
|
-
html_options.merge!("type" => "submit", "value" => name)
|
122
134
|
|
123
|
-
"
|
124
|
-
|
135
|
+
html_options.merge!("type" => "submit", "value" => name)
|
136
|
+
|
137
|
+
"<form method=\"#{form_method}\" action=\"#{escape_once url}\" class=\"button-to\"><div>" +
|
138
|
+
method_tag + tag("input", html_options) + "</div></form>"
|
125
139
|
end
|
126
140
|
|
127
141
|
|
128
|
-
#
|
142
|
+
# DEPRECATED. It is reccommended to use the AssetTagHelper::image_tag within
|
143
|
+
# a link_to method to generate a linked image.
|
144
|
+
#
|
129
145
|
# link_to(image_tag("rss", :size => "30x45", :border => 0), "http://www.example.com")
|
130
146
|
def link_image_to(src, options = {}, html_options = {}, *parameters_for_method_reference)
|
131
147
|
image_options = { "src" => src.include?("/") ? src : "/images/#{src}" }
|
@@ -157,18 +173,42 @@ module ActionView
|
|
157
173
|
link_to(tag("img", image_options), options, html_options, *parameters_for_method_reference)
|
158
174
|
end
|
159
175
|
|
160
|
-
alias_method :link_to_image, :link_image_to
|
176
|
+
alias_method :link_to_image, :link_image_to
|
177
|
+
deprecate :link_to_image => "use link_to(image_tag(...), url)",
|
178
|
+
:link_image_to => "use link_to(image_tag(...), url)"
|
161
179
|
|
162
|
-
# Creates a link tag of the given +name+ using
|
163
|
-
# request uri is the same as the
|
164
|
-
#
|
165
|
-
# to the
|
180
|
+
# Creates a link tag of the given +name+ using a URL created by the set of
|
181
|
+
# +options+ unless the current request uri is the same as the links, in
|
182
|
+
# which case only the name is returned (or the given block is yielded, if
|
183
|
+
# one exists). Refer to the documentation for link_to_unless for block usage.
|
184
|
+
#
|
185
|
+
# <ul id="navbar">
|
186
|
+
# <li><%= link_to_unless_current("Home", { :action => "index" }) %></li>
|
187
|
+
# <li><%= link_to_unless_current("About Us", { :action => "about" }) %></li>
|
188
|
+
# </ul>
|
189
|
+
#
|
190
|
+
# This will render the following HTML when on the about us page:
|
191
|
+
#
|
192
|
+
# <ul id="navbar">
|
193
|
+
# <li><a href="/controller/index">Home</a></li>
|
194
|
+
# <li>About Us</li>
|
195
|
+
# </ul>
|
166
196
|
def link_to_unless_current(name, options = {}, html_options = {}, *parameters_for_method_reference, &block)
|
167
197
|
link_to_unless current_page?(options), name, options, html_options, *parameters_for_method_reference, &block
|
168
198
|
end
|
169
199
|
|
170
|
-
#
|
171
|
-
# is true, in which case only the name is
|
200
|
+
# Creates a link tag of the given +name+ using a URL created by the set of
|
201
|
+
# +options+ unless +condition+ is true, in which case only the name is
|
202
|
+
# returned. To specialize the default behavior, you can pass a block that
|
203
|
+
# accepts the name or the full argument list for link_to_unless (see the example).
|
204
|
+
#
|
205
|
+
# <%= link_to_unless(@current_user.nil?, "Reply", { :action => "reply" }) %>
|
206
|
+
#
|
207
|
+
# This example uses a block to modify the link if the condition isn't met.
|
208
|
+
#
|
209
|
+
# <%= link_to_unless(@current_user.nil?, "Reply", { :action => "reply" }) do |name|
|
210
|
+
# link_to(name, { :controller => "accounts", :action => "signup" })
|
211
|
+
# end %>
|
172
212
|
def link_to_unless(condition, name, options = {}, html_options = {}, *parameters_for_method_reference, &block)
|
173
213
|
if condition
|
174
214
|
if block_given?
|
@@ -181,30 +221,56 @@ module ActionView
|
|
181
221
|
end
|
182
222
|
end
|
183
223
|
|
184
|
-
#
|
185
|
-
# is true, in which case only the name is
|
224
|
+
# Creates a link tag of the given +name+ using a URL created by the set of
|
225
|
+
# +options+ if +condition+ is true, in which case only the name is
|
226
|
+
# returned. To specialize the default behavior, you can pass a block that
|
227
|
+
# accepts the name or the full argument list for link_to_unless (see the examples
|
228
|
+
# in link_to_unless).
|
186
229
|
def link_to_if(condition, name, options = {}, html_options = {}, *parameters_for_method_reference, &block)
|
187
230
|
link_to_unless !condition, name, options, html_options, *parameters_for_method_reference, &block
|
188
231
|
end
|
189
232
|
|
190
|
-
# Creates a link tag
|
191
|
-
# link unless +name+ is specified. Additional
|
233
|
+
# Creates a mailto link tag to the specified +email_address+, which is
|
234
|
+
# also used as the name of the link unless +name+ is specified. Additional
|
235
|
+
# html attributes for the link can be passed in +html_options+.
|
236
|
+
#
|
237
|
+
# mail_to has several methods for hindering email harvestors and customizing
|
238
|
+
# the email itself by passing special keys to +html_options+.
|
239
|
+
#
|
240
|
+
# Special HTML Options:
|
241
|
+
#
|
242
|
+
# * <tt>:encode</tt> - This key will accept the strings "javascript" or "hex".
|
243
|
+
# Passing "javascript" will dynamically create and encode the mailto: link then
|
244
|
+
# eval it into the DOM of the page. This method will not show the link on
|
245
|
+
# the page if the user has JavaScript disabled. Passing "hex" will hex
|
246
|
+
# encode the +email_address+ before outputting the mailto: link.
|
247
|
+
# * <tt>:replace_at</tt> - When the link +name+ isn't provided, the
|
248
|
+
# +email_address+ is used for the link label. You can use this option to
|
249
|
+
# obfuscate the +email_address+ by substituting the @ sign with the string
|
250
|
+
# given as the value.
|
251
|
+
# * <tt>:replace_dot</tt> - When the link +name+ isn't provided, the
|
252
|
+
# +email_address+ is used for the link label. You can use this option to
|
253
|
+
# obfuscate the +email_address+ by substituting the . in the email with the
|
254
|
+
# string given as the value.
|
255
|
+
# * <tt>:subject</tt> - Preset the subject line of the email.
|
256
|
+
# * <tt>:body</tt> - Preset the body of the email.
|
257
|
+
# * <tt>:cc</tt> - Carbon Copy addition recipients on the email.
|
258
|
+
# * <tt>:bcc</tt> - Blind Carbon Copy additional recipients on the email.
|
192
259
|
#
|
193
|
-
# You can also make it difficult for spiders to harvest email address by obfuscating them.
|
194
260
|
# Examples:
|
261
|
+
# mail_to "me@domain.com" # => <a href="mailto:me@domain.com">me@domain.com</a>
|
195
262
|
# mail_to "me@domain.com", "My email", :encode => "javascript" # =>
|
196
|
-
# <script type="text/javascript"
|
263
|
+
# <script type="text/javascript">eval(unescape('%64%6f%63...%6d%65%6e'))</script>
|
197
264
|
#
|
198
265
|
# mail_to "me@domain.com", "My email", :encode => "hex" # =>
|
199
266
|
# <a href="mailto:%6d%65@%64%6f%6d%61%69%6e.%63%6f%6d">My email</a>
|
200
267
|
#
|
201
|
-
#
|
202
|
-
#
|
203
|
-
#
|
204
|
-
#
|
205
|
-
#
|
206
|
-
#
|
207
|
-
# <a href="mailto:me@domain.com?cc="ccaddress@domain.com"&bcc="bccaddress@domain.com"&body="This%20is%20the%20body%20of%20the%20message."&subject="This%20is%20an%20example%20email">My email</a>
|
268
|
+
# mail_to "me@domain.com", nil, :replace_at => "_at_", :replace_dot => "_dot_", :class => "email" # =>
|
269
|
+
# <a href="mailto:me@domain.com" class="email">me_at_domain_dot_com</a>
|
270
|
+
#
|
271
|
+
# mail_to "me@domain.com", "My email", :cc => "ccaddress@domain.com",
|
272
|
+
# :subject => "This is an example email" # =>
|
273
|
+
# <a href="mailto:me@domain.com?cc=ccaddress@domain.com&subject=This%20is%20an%20example%20email">My email</a>
|
208
274
|
def mail_to(email_address, name = nil, html_options = {})
|
209
275
|
html_options = html_options.stringify_keys
|
210
276
|
encode = html_options.delete("encode")
|
@@ -218,17 +284,19 @@ module ActionView
|
|
218
284
|
extras << "subject=#{CGI.escape(subject).gsub("+", "%20")}&" unless subject.nil?
|
219
285
|
extras = "?" << extras.gsub!(/&?$/,"") unless extras.empty?
|
220
286
|
|
287
|
+
email_address = email_address.to_s
|
288
|
+
|
221
289
|
email_address_obfuscated = email_address.dup
|
222
290
|
email_address_obfuscated.gsub!(/@/, html_options.delete("replace_at")) if html_options.has_key?("replace_at")
|
223
291
|
email_address_obfuscated.gsub!(/\./, html_options.delete("replace_dot")) if html_options.has_key?("replace_dot")
|
224
292
|
|
225
|
-
if encode ==
|
226
|
-
tmp = "document.write('#{content_tag("a", name || email_address, html_options.merge({ "href" => "mailto:"+email_address
|
293
|
+
if encode == "javascript"
|
294
|
+
tmp = "document.write('#{content_tag("a", name || email_address, html_options.merge({ "href" => "mailto:"+email_address+extras }))}');"
|
227
295
|
for i in 0...tmp.length
|
228
296
|
string << sprintf("%%%x",tmp[i])
|
229
297
|
end
|
230
298
|
"<script type=\"text/javascript\">eval(unescape('#{string}'))</script>"
|
231
|
-
elsif encode ==
|
299
|
+
elsif encode == "hex"
|
232
300
|
for i in 0...email_address.length
|
233
301
|
if email_address[i,1] =~ /\w/
|
234
302
|
string << sprintf("%%%x",email_address[i])
|
@@ -242,26 +310,42 @@ module ActionView
|
|
242
310
|
end
|
243
311
|
end
|
244
312
|
|
245
|
-
#
|
313
|
+
# True if the current request uri was generated by the given +options+.
|
246
314
|
def current_page?(options)
|
247
|
-
CGI.escapeHTML(url_for(options))
|
315
|
+
url_string = CGI.escapeHTML(url_for(options))
|
316
|
+
request = @controller.request
|
317
|
+
if url_string =~ /^\w+:\/\//
|
318
|
+
url_string == "#{request.protocol}#{request.host_with_port}#{request.request_uri}"
|
319
|
+
else
|
320
|
+
url_string == request.request_uri
|
321
|
+
end
|
248
322
|
end
|
249
323
|
|
250
324
|
private
|
251
325
|
def convert_options_to_javascript!(html_options)
|
252
|
-
confirm, popup
|
326
|
+
confirm, popup = html_options.delete("confirm"), html_options.delete("popup")
|
327
|
+
|
328
|
+
# post is deprecated, but if its specified and method is not, assume that method = :post
|
329
|
+
method, post = html_options.delete("method"), html_options.delete("post")
|
330
|
+
if !method && post
|
331
|
+
ActiveSupport::Deprecation.warn(
|
332
|
+
"Passing :post as a link modifier is deprecated. " +
|
333
|
+
"Use :method => \"post\" instead. :post will be removed in Rails 2.0."
|
334
|
+
)
|
335
|
+
method = :post
|
336
|
+
end
|
253
337
|
|
254
338
|
html_options["onclick"] = case
|
255
|
-
when popup &&
|
339
|
+
when popup && method
|
256
340
|
raise ActionView::ActionViewError, "You can't use :popup and :post in the same link"
|
257
341
|
when confirm && popup
|
258
342
|
"if (#{confirm_javascript_function(confirm)}) { #{popup_javascript_function(popup)} };return false;"
|
259
|
-
when confirm &&
|
260
|
-
"if (#{confirm_javascript_function(confirm)}) { #{
|
343
|
+
when confirm && method
|
344
|
+
"if (#{confirm_javascript_function(confirm)}) { #{method_javascript_function(method)} };return false;"
|
261
345
|
when confirm
|
262
346
|
"return #{confirm_javascript_function(confirm)};"
|
263
|
-
when
|
264
|
-
"#{
|
347
|
+
when method
|
348
|
+
"#{method_javascript_function(method)}return false;"
|
265
349
|
when popup
|
266
350
|
popup_javascript_function(popup) + 'return false;'
|
267
351
|
else
|
@@ -277,8 +361,17 @@ module ActionView
|
|
277
361
|
popup.is_a?(Array) ? "window.open(this.href,'#{popup.first}','#{popup.last}');" : "window.open(this.href);"
|
278
362
|
end
|
279
363
|
|
280
|
-
def
|
281
|
-
|
364
|
+
def method_javascript_function(method)
|
365
|
+
submit_function =
|
366
|
+
"var f = document.createElement('form'); f.style.display = 'none'; " +
|
367
|
+
"this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;"
|
368
|
+
|
369
|
+
unless method == :post
|
370
|
+
submit_function << "var m = document.createElement('input'); m.setAttribute('type', 'hidden'); "
|
371
|
+
submit_function << "m.setAttribute('name', '_method'); m.setAttribute('value', '#{method}'); f.appendChild(m);"
|
372
|
+
end
|
373
|
+
|
374
|
+
submit_function << "f.submit();"
|
282
375
|
end
|
283
376
|
|
284
377
|
# Processes the _html_options_ hash, converting the boolean
|
@@ -6,16 +6,22 @@ module ActionView
|
|
6
6
|
|
7
7
|
attr_reader :original_exception
|
8
8
|
|
9
|
-
def initialize(base_path,
|
10
|
-
@base_path, @assigns, @source, @original_exception =
|
11
|
-
base_path, assigns, source, original_exception
|
12
|
-
@
|
9
|
+
def initialize(base_path, file_path, assigns, source, original_exception)
|
10
|
+
@base_path, @assigns, @source, @original_exception =
|
11
|
+
base_path, assigns.dup, source, original_exception
|
12
|
+
@file_path = file_path
|
13
|
+
|
14
|
+
remove_deprecated_assigns!
|
13
15
|
end
|
14
|
-
|
16
|
+
|
15
17
|
def message
|
16
|
-
original_exception.message
|
18
|
+
ActiveSupport::Deprecation.silence { original_exception.message }
|
19
|
+
end
|
20
|
+
|
21
|
+
def clean_backtrace
|
22
|
+
original_exception.clean_backtrace
|
17
23
|
end
|
18
|
-
|
24
|
+
|
19
25
|
def sub_template_message
|
20
26
|
if @sub_templates
|
21
27
|
"Trace of template inclusion: " +
|
@@ -24,63 +30,81 @@ module ActionView
|
|
24
30
|
""
|
25
31
|
end
|
26
32
|
end
|
27
|
-
|
28
|
-
def source_extract(indention = 0)
|
29
|
-
source_code = IO.readlines(@file_name)
|
30
|
-
|
31
|
-
start_on_line = [ line_number - SOURCE_CODE_RADIUS - 1, 0 ].max
|
32
|
-
end_on_line = [ line_number + SOURCE_CODE_RADIUS - 1, source_code.length].min
|
33
33
|
|
34
|
+
def source_extract(indentation = 0)
|
35
|
+
return unless num = line_number
|
36
|
+
num = num.to_i
|
37
|
+
|
38
|
+
source_code = IO.readlines(@file_path)
|
39
|
+
|
40
|
+
start_on_line = [ num - SOURCE_CODE_RADIUS - 1, 0 ].max
|
41
|
+
end_on_line = [ num + SOURCE_CODE_RADIUS - 1, source_code.length].min
|
42
|
+
|
43
|
+
indent = ' ' * indentation
|
34
44
|
line_counter = start_on_line
|
35
|
-
|
45
|
+
|
46
|
+
source_code[start_on_line..end_on_line].sum do |line|
|
36
47
|
line_counter += 1
|
37
|
-
"#{
|
48
|
+
"#{indent}#{line_counter}: #{line}"
|
38
49
|
end
|
39
|
-
|
40
|
-
extract.join
|
41
50
|
end
|
42
51
|
|
43
|
-
def sub_template_of(
|
52
|
+
def sub_template_of(template_path)
|
44
53
|
@sub_templates ||= []
|
45
|
-
@sub_templates <<
|
54
|
+
@sub_templates << template_path
|
46
55
|
end
|
47
|
-
|
56
|
+
|
48
57
|
def line_number
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
58
|
+
@line_number ||=
|
59
|
+
if file_name
|
60
|
+
regexp = /#{Regexp.escape File.basename(file_name)}:(\d+)/
|
61
|
+
|
62
|
+
$1 if message =~ regexp or clean_backtrace.find { |line| line =~ regexp }
|
53
63
|
end
|
54
|
-
end
|
55
|
-
0
|
56
64
|
end
|
57
|
-
|
65
|
+
|
58
66
|
def file_name
|
59
|
-
stripped = strip_base_path(@
|
60
|
-
stripped
|
67
|
+
stripped = strip_base_path(@file_path)
|
68
|
+
stripped.slice!(0,1) if stripped[0] == ?/
|
69
|
+
stripped
|
61
70
|
end
|
62
|
-
|
71
|
+
|
63
72
|
def to_s
|
64
|
-
"\n\n#{self.class} (#{message})
|
65
|
-
|
66
|
-
original_exception.clean_backtrace.join("\n ") +
|
67
|
-
"\n\n"
|
73
|
+
"\n\n#{self.class} (#{message}) #{source_location}:\n" +
|
74
|
+
"#{source_extract}\n #{clean_backtrace.join("\n ")}\n\n"
|
68
75
|
end
|
69
76
|
|
70
77
|
def backtrace
|
71
|
-
[
|
72
|
-
"
|
73
|
-
|
78
|
+
[
|
79
|
+
"#{source_location.capitalize}\n\n#{source_extract(4)}\n " +
|
80
|
+
clean_backtrace.join("\n ")
|
74
81
|
]
|
75
82
|
end
|
76
83
|
|
77
84
|
private
|
78
|
-
def
|
79
|
-
|
80
|
-
|
85
|
+
def remove_deprecated_assigns!
|
86
|
+
ActionController::Base::DEPRECATED_INSTANCE_VARIABLES.each do |ivar|
|
87
|
+
@assigns.delete(ivar)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def strip_base_path(path)
|
92
|
+
File.expand_path(path).
|
93
|
+
gsub(/^#{Regexp.escape File.expand_path(RAILS_ROOT)}/, '').
|
94
|
+
gsub(@base_path, "")
|
95
|
+
end
|
96
|
+
|
97
|
+
def source_location
|
98
|
+
if line_number
|
99
|
+
"on line ##{line_number} of "
|
100
|
+
else
|
101
|
+
'in '
|
102
|
+
end + file_name
|
81
103
|
end
|
82
104
|
end
|
83
105
|
end
|
84
106
|
|
85
|
-
|
86
|
-
Exception::TraceSubstitutions << [
|
107
|
+
if defined?(Exception::TraceSubstitutions)
|
108
|
+
Exception::TraceSubstitutions << [/:in\s+`_run_(html|xml).*'\s*$/, '']
|
109
|
+
Exception::TraceSubstitutions << [%r{^\s*#{Regexp.escape RAILS_ROOT}}, '#{RAILS_ROOT}'] if defined?(RAILS_ROOT)
|
110
|
+
end
|