actionpack 3.2.22.5 → 4.0.0.beta1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +641 -418
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -288
- data/lib/abstract_controller.rb +1 -8
- data/lib/abstract_controller/asset_paths.rb +2 -2
- data/lib/abstract_controller/base.rb +39 -37
- data/lib/abstract_controller/callbacks.rb +101 -82
- data/lib/abstract_controller/collector.rb +7 -3
- data/lib/abstract_controller/helpers.rb +23 -11
- data/lib/abstract_controller/layouts.rb +68 -73
- data/lib/abstract_controller/logger.rb +1 -2
- data/lib/abstract_controller/rendering.rb +22 -13
- data/lib/abstract_controller/translation.rb +16 -1
- data/lib/abstract_controller/url_for.rb +6 -6
- data/lib/abstract_controller/view_paths.rb +1 -1
- data/lib/action_controller.rb +15 -6
- data/lib/action_controller/base.rb +46 -22
- data/lib/action_controller/caching.rb +46 -33
- data/lib/action_controller/caching/fragments.rb +23 -53
- data/lib/action_controller/deprecated.rb +5 -1
- data/lib/action_controller/deprecated/integration_test.rb +3 -0
- data/lib/action_controller/log_subscriber.rb +11 -8
- data/lib/action_controller/metal.rb +16 -30
- data/lib/action_controller/metal/conditional_get.rb +76 -32
- data/lib/action_controller/metal/data_streaming.rb +20 -26
- data/lib/action_controller/metal/exceptions.rb +19 -6
- data/lib/action_controller/metal/flash.rb +24 -9
- data/lib/action_controller/metal/force_ssl.rb +32 -9
- data/lib/action_controller/metal/head.rb +25 -4
- data/lib/action_controller/metal/helpers.rb +6 -9
- data/lib/action_controller/metal/hide_actions.rb +1 -2
- data/lib/action_controller/metal/http_authentication.rb +105 -87
- data/lib/action_controller/metal/implicit_render.rb +1 -1
- data/lib/action_controller/metal/instrumentation.rb +2 -1
- data/lib/action_controller/metal/live.rb +141 -0
- data/lib/action_controller/metal/mime_responds.rb +161 -47
- data/lib/action_controller/metal/params_wrapper.rb +112 -74
- data/lib/action_controller/metal/rack_delegation.rb +9 -3
- data/lib/action_controller/metal/redirecting.rb +15 -20
- data/lib/action_controller/metal/renderers.rb +11 -9
- data/lib/action_controller/metal/rendering.rb +8 -0
- data/lib/action_controller/metal/request_forgery_protection.rb +112 -19
- data/lib/action_controller/metal/responder.rb +20 -19
- data/lib/action_controller/metal/streaming.rb +12 -18
- data/lib/action_controller/metal/strong_parameters.rb +516 -0
- data/lib/action_controller/metal/testing.rb +13 -18
- data/lib/action_controller/metal/url_for.rb +27 -25
- data/lib/action_controller/model_naming.rb +12 -0
- data/lib/action_controller/railtie.rb +33 -17
- data/lib/action_controller/railties/helpers.rb +22 -0
- data/lib/action_controller/record_identifier.rb +18 -72
- data/lib/action_controller/test_case.rb +215 -123
- data/lib/action_controller/vendor/html-scanner.rb +4 -19
- data/lib/action_dispatch.rb +27 -19
- data/lib/action_dispatch/http/cache.rb +63 -11
- data/lib/action_dispatch/http/filter_parameters.rb +18 -8
- data/lib/action_dispatch/http/filter_redirect.rb +37 -0
- data/lib/action_dispatch/http/headers.rb +27 -19
- data/lib/action_dispatch/http/mime_negotiation.rb +25 -2
- data/lib/action_dispatch/http/mime_type.rb +145 -113
- data/lib/action_dispatch/http/mime_types.rb +1 -1
- data/lib/action_dispatch/http/parameter_filter.rb +44 -46
- data/lib/action_dispatch/http/parameters.rb +12 -5
- data/lib/action_dispatch/http/rack_cache.rb +2 -3
- data/lib/action_dispatch/http/request.rb +49 -18
- data/lib/action_dispatch/http/response.rb +129 -35
- data/lib/action_dispatch/http/upload.rb +60 -17
- data/lib/action_dispatch/http/url.rb +53 -31
- data/lib/action_dispatch/journey.rb +5 -0
- data/lib/action_dispatch/journey/backwards.rb +5 -0
- data/lib/action_dispatch/journey/formatter.rb +146 -0
- data/lib/action_dispatch/journey/gtg/builder.rb +162 -0
- data/lib/action_dispatch/journey/gtg/simulator.rb +44 -0
- data/lib/action_dispatch/journey/gtg/transition_table.rb +156 -0
- data/lib/action_dispatch/journey/nfa/builder.rb +76 -0
- data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
- data/lib/action_dispatch/journey/nfa/simulator.rb +47 -0
- data/lib/action_dispatch/journey/nfa/transition_table.rb +163 -0
- data/lib/action_dispatch/journey/nodes/node.rb +124 -0
- data/lib/action_dispatch/journey/parser.rb +206 -0
- data/lib/action_dispatch/journey/parser.y +47 -0
- data/lib/action_dispatch/journey/parser_extras.rb +23 -0
- data/lib/action_dispatch/journey/path/pattern.rb +196 -0
- data/lib/action_dispatch/journey/route.rb +116 -0
- data/lib/action_dispatch/journey/router.rb +164 -0
- data/lib/action_dispatch/journey/router/strexp.rb +24 -0
- data/lib/action_dispatch/journey/router/utils.rb +54 -0
- data/lib/action_dispatch/journey/routes.rb +75 -0
- data/lib/action_dispatch/journey/scanner.rb +61 -0
- data/lib/action_dispatch/journey/visitors.rb +189 -0
- data/lib/action_dispatch/journey/visualizer/fsm.css +34 -0
- data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
- data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
- data/lib/action_dispatch/middleware/callbacks.rb +9 -4
- data/lib/action_dispatch/middleware/cookies.rb +168 -57
- data/lib/action_dispatch/middleware/debug_exceptions.rb +26 -17
- data/lib/action_dispatch/middleware/exception_wrapper.rb +27 -3
- data/lib/action_dispatch/middleware/flash.rb +58 -58
- data/lib/action_dispatch/middleware/params_parser.rb +14 -29
- data/lib/action_dispatch/middleware/public_exceptions.rb +31 -14
- data/lib/action_dispatch/middleware/reloader.rb +6 -6
- data/lib/action_dispatch/middleware/remote_ip.rb +145 -39
- data/lib/action_dispatch/middleware/request_id.rb +2 -6
- data/lib/action_dispatch/middleware/session/abstract_store.rb +22 -20
- data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
- data/lib/action_dispatch/middleware/session/cookie_store.rb +81 -7
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +12 -45
- data/lib/action_dispatch/middleware/ssl.rb +70 -0
- data/lib/action_dispatch/middleware/stack.rb +6 -1
- data/lib/action_dispatch/middleware/static.rb +5 -24
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +14 -11
- data/lib/action_dispatch/middleware/templates/rescues/_source.erb +25 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +15 -9
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +121 -5
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +7 -2
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +30 -15
- data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +39 -13
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +6 -2
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +144 -0
- data/lib/action_dispatch/railtie.rb +16 -6
- data/lib/action_dispatch/request/session.rb +181 -0
- data/lib/action_dispatch/routing.rb +41 -40
- data/lib/action_dispatch/routing/inspector.rb +240 -0
- data/lib/action_dispatch/routing/mapper.rb +501 -273
- data/lib/action_dispatch/routing/polymorphic_routes.rb +16 -20
- data/lib/action_dispatch/routing/redirection.rb +46 -29
- data/lib/action_dispatch/routing/route_set.rb +203 -164
- data/lib/action_dispatch/routing/routes_proxy.rb +2 -0
- data/lib/action_dispatch/routing/url_for.rb +48 -33
- data/lib/action_dispatch/testing/assertions/dom.rb +3 -13
- data/lib/action_dispatch/testing/assertions/response.rb +32 -40
- data/lib/action_dispatch/testing/assertions/routing.rb +40 -39
- data/lib/action_dispatch/testing/assertions/selector.rb +15 -20
- data/lib/action_dispatch/testing/assertions/tag.rb +20 -23
- data/lib/action_dispatch/testing/integration.rb +41 -22
- data/lib/action_dispatch/testing/test_process.rb +9 -6
- data/lib/action_dispatch/testing/test_request.rb +7 -3
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/version.rb +4 -4
- data/lib/action_view.rb +17 -8
- data/lib/action_view/base.rb +15 -34
- data/lib/action_view/buffers.rb +1 -1
- data/lib/action_view/context.rb +4 -4
- data/lib/action_view/dependency_tracker.rb +91 -0
- data/lib/action_view/digestor.rb +85 -0
- data/lib/action_view/flows.rb +1 -4
- data/lib/action_view/helpers.rb +2 -4
- data/lib/action_view/helpers/active_model_helper.rb +3 -4
- data/lib/action_view/helpers/asset_tag_helper.rb +211 -353
- data/lib/action_view/helpers/asset_url_helper.rb +354 -0
- data/lib/action_view/helpers/atom_feed_helper.rb +13 -10
- data/lib/action_view/helpers/cache_helper.rb +150 -18
- data/lib/action_view/helpers/capture_helper.rb +42 -29
- data/lib/action_view/helpers/csrf_helper.rb +0 -2
- data/lib/action_view/helpers/date_helper.rb +268 -247
- data/lib/action_view/helpers/debug_helper.rb +10 -11
- data/lib/action_view/helpers/form_helper.rb +904 -547
- data/lib/action_view/helpers/form_options_helper.rb +341 -166
- data/lib/action_view/helpers/form_tag_helper.rb +188 -88
- data/lib/action_view/helpers/javascript_helper.rb +23 -16
- data/lib/action_view/helpers/number_helper.rb +148 -354
- data/lib/action_view/helpers/output_safety_helper.rb +3 -3
- data/lib/action_view/helpers/record_tag_helper.rb +17 -22
- data/lib/action_view/helpers/rendering_helper.rb +2 -4
- data/lib/action_view/helpers/sanitize_helper.rb +3 -6
- data/lib/action_view/helpers/tag_helper.rb +43 -37
- data/lib/action_view/helpers/tags.rb +39 -0
- data/lib/action_view/helpers/tags/base.rb +148 -0
- data/lib/action_view/helpers/tags/check_box.rb +64 -0
- data/lib/action_view/helpers/tags/checkable.rb +16 -0
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +43 -0
- data/lib/action_view/helpers/tags/collection_helpers.rb +83 -0
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +36 -0
- data/lib/action_view/helpers/tags/collection_select.rb +28 -0
- data/lib/action_view/helpers/tags/color_field.rb +25 -0
- data/lib/action_view/helpers/tags/date_field.rb +13 -0
- data/lib/action_view/helpers/tags/date_select.rb +72 -0
- data/lib/action_view/helpers/tags/datetime_field.rb +22 -0
- data/lib/action_view/helpers/tags/datetime_local_field.rb +19 -0
- data/lib/action_view/helpers/tags/datetime_select.rb +8 -0
- data/lib/action_view/helpers/tags/email_field.rb +8 -0
- data/lib/action_view/helpers/tags/file_field.rb +8 -0
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +29 -0
- data/lib/action_view/helpers/tags/hidden_field.rb +8 -0
- data/lib/action_view/helpers/tags/label.rb +65 -0
- data/lib/action_view/helpers/tags/month_field.rb +13 -0
- data/lib/action_view/helpers/tags/number_field.rb +18 -0
- data/lib/action_view/helpers/tags/password_field.rb +12 -0
- data/lib/action_view/helpers/tags/radio_button.rb +31 -0
- data/lib/action_view/helpers/tags/range_field.rb +8 -0
- data/lib/action_view/helpers/tags/search_field.rb +24 -0
- data/lib/action_view/helpers/tags/select.rb +41 -0
- data/lib/action_view/helpers/tags/tel_field.rb +8 -0
- data/lib/action_view/helpers/tags/text_area.rb +18 -0
- data/lib/action_view/helpers/tags/text_field.rb +29 -0
- data/lib/action_view/helpers/tags/time_field.rb +13 -0
- data/lib/action_view/helpers/tags/time_select.rb +8 -0
- data/lib/action_view/helpers/tags/time_zone_select.rb +20 -0
- data/lib/action_view/helpers/tags/url_field.rb +8 -0
- data/lib/action_view/helpers/tags/week_field.rb +13 -0
- data/lib/action_view/helpers/text_helper.rb +126 -113
- data/lib/action_view/helpers/translation_helper.rb +32 -16
- data/lib/action_view/helpers/url_helper.rb +200 -271
- data/lib/action_view/locale/en.yml +1 -105
- data/lib/action_view/log_subscriber.rb +6 -4
- data/lib/action_view/lookup_context.rb +15 -39
- data/lib/action_view/model_naming.rb +12 -0
- data/lib/action_view/path_set.rb +9 -39
- data/lib/action_view/railtie.rb +6 -22
- data/lib/action_view/record_identifier.rb +84 -0
- data/lib/action_view/renderer/abstract_renderer.rb +10 -19
- data/lib/action_view/renderer/partial_renderer.rb +144 -81
- data/lib/action_view/renderer/renderer.rb +2 -19
- data/lib/action_view/renderer/streaming_template_renderer.rb +2 -5
- data/lib/action_view/renderer/template_renderer.rb +14 -13
- data/lib/action_view/routing_url_for.rb +107 -0
- data/lib/action_view/template.rb +22 -21
- data/lib/action_view/template/error.rb +22 -12
- data/lib/action_view/template/handlers.rb +12 -9
- data/lib/action_view/template/handlers/builder.rb +1 -1
- data/lib/action_view/template/handlers/erb.rb +11 -16
- data/lib/action_view/template/handlers/raw.rb +11 -0
- data/lib/action_view/template/resolver.rb +111 -83
- data/lib/action_view/template/text.rb +12 -8
- data/lib/action_view/template/types.rb +57 -0
- data/lib/action_view/test_case.rb +66 -43
- data/lib/action_view/testing/resolvers.rb +3 -2
- data/lib/action_view/vendor/html-scanner.rb +20 -0
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/document.rb +0 -0
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/node.rb +12 -12
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/sanitizer.rb +18 -7
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/selector.rb +1 -1
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/tokenizer.rb +1 -1
- data/lib/{action_controller → action_view}/vendor/html-scanner/html/version.rb +0 -0
- metadata +135 -125
- data/lib/action_controller/caching/actions.rb +0 -185
- data/lib/action_controller/caching/pages.rb +0 -187
- data/lib/action_controller/caching/sweeping.rb +0 -97
- data/lib/action_controller/deprecated/performance_test.rb +0 -1
- data/lib/action_controller/metal/compatibility.rb +0 -65
- data/lib/action_controller/metal/session_management.rb +0 -14
- data/lib/action_controller/railties/paths.rb +0 -25
- data/lib/action_dispatch/middleware/best_standards_support.rb +0 -30
- data/lib/action_dispatch/middleware/body_proxy.rb +0 -30
- data/lib/action_dispatch/middleware/head.rb +0 -18
- data/lib/action_dispatch/middleware/rescue.rb +0 -26
- data/lib/action_dispatch/testing/performance_test.rb +0 -10
- data/lib/action_view/asset_paths.rb +0 -142
- data/lib/action_view/helpers/asset_paths.rb +0 -7
- data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +0 -146
- data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +0 -93
- data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +0 -193
- data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +0 -148
- data/lib/sprockets/assets.rake +0 -99
- data/lib/sprockets/bootstrap.rb +0 -37
- data/lib/sprockets/compressors.rb +0 -83
- data/lib/sprockets/helpers.rb +0 -6
- data/lib/sprockets/helpers/isolated_helper.rb +0 -13
- data/lib/sprockets/helpers/rails_helper.rb +0 -182
- data/lib/sprockets/railtie.rb +0 -62
- data/lib/sprockets/static_compiler.rb +0 -56
@@ -1,14 +1,24 @@
|
|
1
1
|
require 'action_view/helpers/tag_helper'
|
2
2
|
require 'i18n/exceptions'
|
3
3
|
|
4
|
+
module I18n
|
5
|
+
class ExceptionHandler
|
6
|
+
include Module.new {
|
7
|
+
def call(exception, locale, key, options)
|
8
|
+
exception.is_a?(MissingTranslation) && options[:rescue_format] == :html ? super.html_safe : super
|
9
|
+
end
|
10
|
+
}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
4
14
|
module ActionView
|
5
15
|
# = Action View Translation Helpers
|
6
16
|
module Helpers
|
7
17
|
module TranslationHelper
|
8
18
|
# Delegates to <tt>I18n#translate</tt> but also performs three additional functions.
|
9
19
|
#
|
10
|
-
# First, it
|
11
|
-
# into inline spans that
|
20
|
+
# First, it'll pass the <tt>rescue_format: :html</tt> option to I18n so that any
|
21
|
+
# thrown +MissingTranslation+ messages will be turned into inline spans that
|
12
22
|
#
|
13
23
|
# * have a "translation-missing" class set,
|
14
24
|
# * contain the missing key as a title attribute and
|
@@ -34,15 +44,8 @@ module ActionView
|
|
34
44
|
# naming convention helps to identify translations that include HTML tags so that
|
35
45
|
# you know what kind of output to expect when you call translate in a template.
|
36
46
|
def translate(key, options = {})
|
37
|
-
|
38
|
-
|
39
|
-
if options.key?(:raise) || options.key?(:rescue_format)
|
40
|
-
raise_error = options[:raise] || options[:rescue_format]
|
41
|
-
else
|
42
|
-
raise_error = false
|
43
|
-
options[:raise] = true
|
44
|
-
end
|
45
|
-
|
47
|
+
options.merge!(:rescue_format => :html) unless options.key?(:rescue_format)
|
48
|
+
options[:default] = wrap_translate_defaults(options[:default]) if options[:default]
|
46
49
|
if html_safe_translation_key?(key)
|
47
50
|
html_safe_options = options.dup
|
48
51
|
options.except(*I18n::RESERVED_KEYS).each do |name, value|
|
@@ -56,15 +59,13 @@ module ActionView
|
|
56
59
|
else
|
57
60
|
I18n.translate(scope_key_by_partial(key), options)
|
58
61
|
end
|
59
|
-
rescue I18n::MissingTranslationData => e
|
60
|
-
raise e if raise_error
|
61
|
-
|
62
|
-
keys = I18n.normalize_keys(e.locale, e.key, e.options[:scope])
|
63
|
-
content_tag('span', keys.last.to_s.titleize, :class => 'translation_missing', :title => "translation missing: #{keys.join('.')}")
|
64
62
|
end
|
65
63
|
alias :t :translate
|
66
64
|
|
67
65
|
# Delegates to <tt>I18n.localize</tt> with no additional functionality.
|
66
|
+
#
|
67
|
+
# See http://rubydoc.info/github/svenfuchs/i18n/master/I18n/Backend/Base:localize
|
68
|
+
# for more information.
|
68
69
|
def localize(*args)
|
69
70
|
I18n.localize(*args)
|
70
71
|
end
|
@@ -86,6 +87,21 @@ module ActionView
|
|
86
87
|
def html_safe_translation_key?(key)
|
87
88
|
key.to_s =~ /(\b|_|\.)html$/
|
88
89
|
end
|
90
|
+
|
91
|
+
def wrap_translate_defaults(defaults)
|
92
|
+
new_defaults = []
|
93
|
+
defaults = Array(defaults)
|
94
|
+
while key = defaults.shift
|
95
|
+
if key.is_a?(Symbol)
|
96
|
+
new_defaults << lambda { |_, options| translate key, options.merge(:default => defaults) }
|
97
|
+
break
|
98
|
+
else
|
99
|
+
new_defaults << key
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
new_defaults
|
104
|
+
end
|
89
105
|
end
|
90
106
|
end
|
91
107
|
end
|
@@ -2,7 +2,6 @@ require 'action_view/helpers/javascript_helper'
|
|
2
2
|
require 'active_support/core_ext/array/access'
|
3
3
|
require 'active_support/core_ext/hash/keys'
|
4
4
|
require 'active_support/core_ext/string/output_safety'
|
5
|
-
require 'action_dispatch'
|
6
5
|
|
7
6
|
module ActionView
|
8
7
|
# = Action View URL Helpers
|
@@ -20,98 +19,33 @@ module ActionView
|
|
20
19
|
|
21
20
|
extend ActiveSupport::Concern
|
22
21
|
|
23
|
-
include ActionDispatch::Routing::UrlFor
|
24
22
|
include TagHelper
|
25
23
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
# Need to map default url options to controller one.
|
31
|
-
# def default_url_options(*args) #:nodoc:
|
32
|
-
# controller.send(:default_url_options, *args)
|
33
|
-
# end
|
34
|
-
#
|
35
|
-
def url_options
|
36
|
-
return super unless controller.respond_to?(:url_options)
|
37
|
-
controller.url_options
|
24
|
+
module ClassMethods
|
25
|
+
def _url_for_modules
|
26
|
+
ActionView::RoutingUrlFor
|
27
|
+
end
|
38
28
|
end
|
39
29
|
|
40
|
-
#
|
41
|
-
|
42
|
-
# documentation for <tt>ActionController::Base#url_for</tt>). Note that by default
|
43
|
-
# <tt>:only_path</tt> is <tt>true</tt> so you'll get the relative "/controller/action"
|
44
|
-
# instead of the fully qualified URL like "http://example.com/controller/action".
|
45
|
-
#
|
46
|
-
# ==== Options
|
47
|
-
# * <tt>:anchor</tt> - Specifies the anchor name to be appended to the path.
|
48
|
-
# * <tt>:only_path</tt> - If true, returns the relative URL (omitting the protocol, host name, and port) (<tt>true</tt> by default unless <tt>:host</tt> is specified).
|
49
|
-
# * <tt>:trailing_slash</tt> - If true, adds a trailing slash, as in "/archive/2005/". Note that this
|
50
|
-
# is currently not recommended since it breaks caching.
|
51
|
-
# * <tt>:host</tt> - Overrides the default (current) host if provided.
|
52
|
-
# * <tt>:protocol</tt> - Overrides the default (current) protocol if provided.
|
53
|
-
# * <tt>:user</tt> - Inline HTTP authentication (only plucked out if <tt>:password</tt> is also present).
|
54
|
-
# * <tt>:password</tt> - Inline HTTP authentication (only plucked out if <tt>:user</tt> is also present).
|
55
|
-
#
|
56
|
-
# ==== Relying on named routes
|
57
|
-
#
|
58
|
-
# Passing a record (like an Active Record or Active Resource) instead of a Hash as the options parameter will
|
59
|
-
# trigger the named route for that record. The lookup will happen on the name of the class. So passing a
|
60
|
-
# Workshop object will attempt to use the +workshop_path+ route. If you have a nested route, such as
|
61
|
-
# +admin_workshop_path+ you'll have to call that explicitly (it's impossible for +url_for+ to guess that route).
|
62
|
-
#
|
63
|
-
# ==== Examples
|
64
|
-
# <%= url_for(:action => 'index') %>
|
65
|
-
# # => /blog/
|
66
|
-
#
|
67
|
-
# <%= url_for(:action => 'find', :controller => 'books') %>
|
68
|
-
# # => /books/find
|
69
|
-
#
|
70
|
-
# <%= url_for(:action => 'login', :controller => 'members', :only_path => false, :protocol => 'https') %>
|
71
|
-
# # => https://www.example.com/members/login/
|
72
|
-
#
|
73
|
-
# <%= url_for(:action => 'play', :anchor => 'player') %>
|
74
|
-
# # => /messages/play/#player
|
75
|
-
#
|
76
|
-
# <%= url_for(:action => 'jump', :anchor => 'tax&ship') %>
|
77
|
-
# # => /testing/jump/#tax&ship
|
78
|
-
#
|
79
|
-
# <%= url_for(Workshop.new) %>
|
80
|
-
# # relies on Workshop answering a persisted? call (and in this case returning false)
|
81
|
-
# # => /workshops
|
82
|
-
#
|
83
|
-
# <%= url_for(@workshop) %>
|
84
|
-
# # calls @workshop.to_param which by default returns the id
|
85
|
-
# # => /workshops/5
|
86
|
-
#
|
87
|
-
# # to_param can be re-defined in a model to provide different URL names:
|
88
|
-
# # => /workshops/1-workshop-name
|
89
|
-
#
|
90
|
-
# <%= url_for("http://www.example.com") %>
|
91
|
-
# # => http://www.example.com
|
92
|
-
#
|
93
|
-
# <%= url_for(:back) %>
|
94
|
-
# # if request.env["HTTP_REFERER"] is set to "http://www.example.com"
|
95
|
-
# # => http://www.example.com
|
96
|
-
#
|
97
|
-
# <%= url_for(:back) %>
|
98
|
-
# # if request.env["HTTP_REFERER"] is not set or is blank
|
99
|
-
# # => javascript:history.back()
|
100
|
-
def url_for(options = {})
|
101
|
-
options ||= {}
|
30
|
+
# Basic implementation of url_for to allow use helpers without routes existence
|
31
|
+
def url_for(options = nil) # :nodoc:
|
102
32
|
case options
|
103
33
|
when String
|
104
34
|
options
|
105
|
-
when Hash
|
106
|
-
options = options.symbolize_keys.reverse_merge!(:only_path => options[:host].nil?)
|
107
|
-
super
|
108
35
|
when :back
|
109
|
-
|
36
|
+
_back_url
|
110
37
|
else
|
111
|
-
|
38
|
+
raise ArgumentError, "arguments passed to url_for can't be handled. Please require " +
|
39
|
+
"routes or provide your own implementation"
|
112
40
|
end
|
113
41
|
end
|
114
42
|
|
43
|
+
def _back_url # :nodoc:
|
44
|
+
referrer = controller.respond_to?(:request) && controller.request.env["HTTP_REFERER"]
|
45
|
+
referrer || 'javascript:history.back()'
|
46
|
+
end
|
47
|
+
protected :_back_url
|
48
|
+
|
115
49
|
# Creates a link tag of the given +name+ using a URL created by the set of +options+.
|
116
50
|
# See the valid options in the documentation for +url_for+. It's also possible to
|
117
51
|
# pass a String instead of an options hash, which generates a link tag that uses the
|
@@ -127,8 +61,7 @@ module ActionView
|
|
127
61
|
# # posts_path
|
128
62
|
#
|
129
63
|
# link_to(body, url_options = {}, html_options = {})
|
130
|
-
# # url_options, except :
|
131
|
-
# # is passed to url_for
|
64
|
+
# # url_options, except :method, is passed to url_for
|
132
65
|
#
|
133
66
|
# link_to(options = {}, html_options = {}) do
|
134
67
|
# # name
|
@@ -139,25 +72,33 @@ module ActionView
|
|
139
72
|
# end
|
140
73
|
#
|
141
74
|
# ==== Options
|
142
|
-
# * <tt>:
|
143
|
-
#
|
144
|
-
# processed normally, otherwise no action is taken.
|
145
|
-
# * <tt>:method => symbol of HTTP verb</tt> - This modifier will dynamically
|
75
|
+
# * <tt>:data</tt> - This option can be used to add custom data attributes.
|
76
|
+
# * <tt>method: symbol of HTTP verb</tt> - This modifier will dynamically
|
146
77
|
# create an HTML form and immediately submit the form for processing using
|
147
78
|
# the HTTP verb specified. Useful for having links perform a POST operation
|
148
79
|
# in dangerous actions like deleting a record (which search bots can follow
|
149
|
-
# while spidering your site). Supported verbs are <tt>:post</tt>, <tt>:delete</tt
|
80
|
+
# while spidering your site). Supported verbs are <tt>:post</tt>, <tt>:delete</tt>, <tt>:patch</tt>, and <tt>:put</tt>.
|
150
81
|
# Note that if the user has JavaScript disabled, the request will fall back
|
151
|
-
# to using GET. If <tt
|
82
|
+
# to using GET. If <tt>href: '#'</tt> is used and the user has JavaScript
|
152
83
|
# disabled clicking the link will have no effect. If you are relying on the
|
153
84
|
# POST behavior, you should check for it in your controller's action by using
|
154
|
-
# the request object's methods for <tt>post?</tt>, <tt>delete?</tt
|
155
|
-
# * <tt
|
85
|
+
# the request object's methods for <tt>post?</tt>, <tt>delete?</tt>, <tt>:patch</tt>, or <tt>put?</tt>.
|
86
|
+
# * <tt>remote: true</tt> - This will allow the unobtrusive JavaScript
|
156
87
|
# driver to make an Ajax request to the URL in question instead of following
|
157
88
|
# the link. The drivers each provide mechanisms for listening for the
|
158
89
|
# completion of the Ajax request and performing JavaScript operations once
|
159
90
|
# they're complete
|
160
91
|
#
|
92
|
+
# ==== Data attributes
|
93
|
+
#
|
94
|
+
# * <tt>confirm: 'question?'</tt> - This will allow the unobtrusive JavaScript
|
95
|
+
# driver to prompt with the question specified. If the user accepts, the link is
|
96
|
+
# processed normally, otherwise no action is taken.
|
97
|
+
# * <tt>:disable_with</tt> - Value of this parameter will be
|
98
|
+
# used as the value for a disabled version of the submit
|
99
|
+
# button when the form is submitted. This feature is provided
|
100
|
+
# by the unobtrusive JavaScript driver.
|
101
|
+
#
|
161
102
|
# ==== Examples
|
162
103
|
# Because it relies on +url_for+, +link_to+ supports both older-style controller/action/id arguments
|
163
104
|
# and newer RESTful routes. Current Rails style favors RESTful routes whenever possible, so base
|
@@ -173,7 +114,7 @@ module ActionView
|
|
173
114
|
#
|
174
115
|
# in place of the older more verbose, non-resource-oriented
|
175
116
|
#
|
176
|
-
# link_to "Profile", :
|
117
|
+
# link_to "Profile", controller: "profiles", action: "show", id: @profile
|
177
118
|
# # => <a href="/profiles/show/1">Profile</a>
|
178
119
|
#
|
179
120
|
# Similarly,
|
@@ -183,7 +124,7 @@ module ActionView
|
|
183
124
|
#
|
184
125
|
# is better than
|
185
126
|
#
|
186
|
-
# link_to "Profiles", :
|
127
|
+
# link_to "Profiles", controller: "profiles"
|
187
128
|
# # => <a href="/profiles">Profiles</a>
|
188
129
|
#
|
189
130
|
# You can use a block as well if your link target is hard to fit into the name parameter. ERB example:
|
@@ -197,56 +138,49 @@ module ActionView
|
|
197
138
|
#
|
198
139
|
# Classes and ids for CSS are easy to produce:
|
199
140
|
#
|
200
|
-
# link_to "Articles", articles_path, :
|
141
|
+
# link_to "Articles", articles_path, id: "news", class: "article"
|
201
142
|
# # => <a href="/articles" class="article" id="news">Articles</a>
|
202
143
|
#
|
203
144
|
# Be careful when using the older argument style, as an extra literal hash is needed:
|
204
145
|
#
|
205
|
-
# link_to "Articles", { :
|
146
|
+
# link_to "Articles", { controller: "articles" }, id: "news", class: "article"
|
206
147
|
# # => <a href="/articles" class="article" id="news">Articles</a>
|
207
148
|
#
|
208
149
|
# Leaving the hash off gives the wrong link:
|
209
150
|
#
|
210
|
-
# link_to "WRONG!", :
|
151
|
+
# link_to "WRONG!", controller: "articles", id: "news", class: "article"
|
211
152
|
# # => <a href="/articles/index/news?class=article">WRONG!</a>
|
212
153
|
#
|
213
154
|
# +link_to+ can also produce links with anchors or query strings:
|
214
155
|
#
|
215
|
-
# link_to "Comment wall", profile_path(@profile, :
|
156
|
+
# link_to "Comment wall", profile_path(@profile, anchor: "wall")
|
216
157
|
# # => <a href="/profiles/1#wall">Comment wall</a>
|
217
158
|
#
|
218
|
-
# link_to "Ruby on Rails search", :
|
159
|
+
# link_to "Ruby on Rails search", controller: "searches", query: "ruby on rails"
|
219
160
|
# # => <a href="/searches?query=ruby+on+rails">Ruby on Rails search</a>
|
220
161
|
#
|
221
|
-
# link_to "Nonsense search", searches_path(:
|
162
|
+
# link_to "Nonsense search", searches_path(foo: "bar", baz: "quux")
|
222
163
|
# # => <a href="/searches?foo=bar&baz=quux">Nonsense search</a>
|
223
164
|
#
|
224
|
-
# The
|
165
|
+
# The only option specific to +link_to+ (<tt>:method</tt>) is used as follows:
|
225
166
|
#
|
226
|
-
# link_to
|
227
|
-
# # => <a href=
|
167
|
+
# link_to("Destroy", "http://www.example.com", method: :delete)
|
168
|
+
# # => <a href='http://www.example.com' rel="nofollow" data-method="delete">Destroy</a>
|
228
169
|
#
|
229
|
-
#
|
230
|
-
#
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
else
|
237
|
-
name = args[0]
|
238
|
-
options = args[1] || {}
|
239
|
-
html_options = args[2]
|
170
|
+
# You can also use custom data attributes using the <tt>:data</tt> option:
|
171
|
+
#
|
172
|
+
# link_to "Visit Other Site", "http://www.rubyonrails.org/", data: { confirm: "Are you sure?" }
|
173
|
+
# # => <a href="http://www.rubyonrails.org/" data-confirm="Are you sure?">Visit Other Site</a>
|
174
|
+
def link_to(name = nil, options = nil, html_options = nil, &block)
|
175
|
+
html_options, options = options, name if block_given?
|
176
|
+
options ||= {}
|
240
177
|
|
241
|
-
|
242
|
-
url = url_for(options)
|
178
|
+
html_options = convert_options_to_data_attributes(options, html_options)
|
243
179
|
|
244
|
-
|
245
|
-
|
180
|
+
url = url_for(options)
|
181
|
+
html_options['href'] ||= url
|
246
182
|
|
247
|
-
|
248
|
-
"<a #{href_attr}#{tag_options}>#{ERB::Util.html_escape(name || url)}</a>".html_safe
|
249
|
-
end
|
183
|
+
content_tag(:a, name || url, html_options, &block)
|
250
184
|
end
|
251
185
|
|
252
186
|
# Generates a form containing a single button that submits to the URL created
|
@@ -260,10 +194,9 @@ module ActionView
|
|
260
194
|
# to allow styling of the form itself and its children. This can be changed
|
261
195
|
# using the <tt>:form_class</tt> modifier within +html_options+. You can control
|
262
196
|
# the form submission and input element behavior using +html_options+.
|
263
|
-
# This method accepts the <tt>:method</tt>
|
264
|
-
#
|
265
|
-
#
|
266
|
-
# disable the button by passing <tt>:disabled => true</tt> in +html_options+.
|
197
|
+
# This method accepts the <tt>:method</tt> modifier described in the +link_to+ documentation.
|
198
|
+
# If no <tt>:method</tt> modifier is given, it will default to performing a POST operation.
|
199
|
+
# You can also disable the button by passing <tt>disabled: true</tt> in +html_options+.
|
267
200
|
# If you are using RESTful routes, you can pass the <tt>:method</tt>
|
268
201
|
# to change the HTTP verb used to submit the form.
|
269
202
|
#
|
@@ -272,89 +205,114 @@ module ActionView
|
|
272
205
|
#
|
273
206
|
# There are a few special +html_options+:
|
274
207
|
# * <tt>:method</tt> - Symbol of HTTP verb. Supported verbs are <tt>:post</tt>, <tt>:get</tt>,
|
275
|
-
# <tt>:delete</tt
|
208
|
+
# <tt>:delete</tt>, <tt>:patch</tt>, and <tt>:put</tt>. By default it will be <tt>:post</tt>.
|
276
209
|
# * <tt>:disabled</tt> - If set to true, it will generate a disabled button.
|
277
|
-
# * <tt>:
|
278
|
-
# prompt with the question specified. If the user accepts, the link is
|
279
|
-
# processed normally, otherwise no action is taken.
|
210
|
+
# * <tt>:data</tt> - This option can be used to add custom data attributes.
|
280
211
|
# * <tt>:remote</tt> - If set to true, will allow the Unobtrusive JavaScript drivers to control the
|
281
212
|
# submit behavior. By default this behavior is an ajax submit.
|
282
213
|
# * <tt>:form</tt> - This hash will be form attributes
|
283
214
|
# * <tt>:form_class</tt> - This controls the class of the form within which the submit button will
|
284
215
|
# be placed
|
285
216
|
#
|
217
|
+
# ==== Data attributes
|
218
|
+
#
|
219
|
+
# * <tt>:confirm</tt> - This will use the unobtrusive JavaScript driver to
|
220
|
+
# prompt with the question specified. If the user accepts, the link is
|
221
|
+
# processed normally, otherwise no action is taken.
|
222
|
+
# * <tt>:disable_with</tt> - Value of this parameter will be
|
223
|
+
# used as the value for a disabled version of the submit
|
224
|
+
# button when the form is submitted. This feature is provided
|
225
|
+
# by the unobtrusive JavaScript driver.
|
226
|
+
#
|
286
227
|
# ==== Examples
|
287
|
-
# <%= button_to "New", :
|
228
|
+
# <%= button_to "New", action: "new" %>
|
288
229
|
# # => "<form method="post" action="/controller/new" class="button_to">
|
289
230
|
# # <div><input value="New" type="submit" /></div>
|
290
231
|
# # </form>"
|
291
232
|
#
|
233
|
+
# <%= button_to [:make_happy, @user] do %>
|
234
|
+
# Make happy <strong><%= @user.name %></strong>
|
235
|
+
# <% end %>
|
236
|
+
# # => "<form method="post" action="/users/1/make_happy" class="button_to">
|
237
|
+
# # <div>
|
238
|
+
# # <button type="submit">
|
239
|
+
# # Make happy <strong><%= @user.name %></strong>
|
240
|
+
# # </button>
|
241
|
+
# # </div>
|
242
|
+
# # </form>"
|
292
243
|
#
|
293
|
-
# <%= button_to "New", :
|
244
|
+
# <%= button_to "New", { action: "new" }, form_class: "new-thing" %>
|
294
245
|
# # => "<form method="post" action="/controller/new" class="new-thing">
|
295
246
|
# # <div><input value="New" type="submit" /></div>
|
296
247
|
# # </form>"
|
297
248
|
#
|
298
249
|
#
|
299
|
-
# <%= button_to "Create", :
|
250
|
+
# <%= button_to "Create", { action: "create" }, remote: true, form: { "data-type" => "json" } %>
|
300
251
|
# # => "<form method="post" action="/images/create" class="button_to" data-remote="true" data-type="json">
|
301
|
-
# # <div
|
252
|
+
# # <div>
|
253
|
+
# # <input value="Create" type="submit" />
|
254
|
+
# # <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"/>
|
255
|
+
# # </div>
|
302
256
|
# # </form>"
|
303
257
|
#
|
304
|
-
#
|
305
|
-
# <%= button_to "Delete Image", { :
|
306
|
-
#
|
258
|
+
#
|
259
|
+
# <%= button_to "Delete Image", { action: "delete", id: @image.id },
|
260
|
+
# method: :delete, data: { confirm: "Are you sure?" } %>
|
307
261
|
# # => "<form method="post" action="/images/delete/1" class="button_to">
|
308
262
|
# # <div>
|
309
263
|
# # <input type="hidden" name="_method" value="delete" />
|
310
|
-
# # <input data-confirm='Are you sure?' value="Delete" type="submit" />
|
264
|
+
# # <input data-confirm='Are you sure?' value="Delete Image" type="submit" />
|
265
|
+
# # <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"/>
|
311
266
|
# # </div>
|
312
267
|
# # </form>"
|
313
268
|
#
|
314
269
|
#
|
315
|
-
# <%= button_to('Destroy', 'http://www.example.com',
|
316
|
-
# :
|
270
|
+
# <%= button_to('Destroy', 'http://www.example.com',
|
271
|
+
# method: "delete", remote: true, data: { confirm: 'Are you sure?', disable_with: 'loading...' }) %>
|
317
272
|
# # => "<form class='button_to' method='post' action='http://www.example.com' data-remote='true'>
|
318
273
|
# # <div>
|
319
274
|
# # <input name='_method' value='delete' type='hidden' />
|
320
|
-
# # <input value='Destroy' type='submit'
|
275
|
+
# # <input value='Destroy' type='submit' data-disable-with='loading...' data-confirm='Are you sure?' />
|
276
|
+
# # <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"/>
|
321
277
|
# # </div>
|
322
278
|
# # </form>"
|
323
279
|
# #
|
324
|
-
def button_to(name, options =
|
280
|
+
def button_to(name = nil, options = nil, html_options = nil, &block)
|
281
|
+
html_options, options = options, name if block_given?
|
282
|
+
options ||= {}
|
283
|
+
html_options ||= {}
|
284
|
+
|
325
285
|
html_options = html_options.stringify_keys
|
326
|
-
convert_boolean_attributes!(html_options, %w(
|
286
|
+
convert_boolean_attributes!(html_options, %w(disabled))
|
327
287
|
|
328
|
-
|
329
|
-
|
330
|
-
method_tag = tag('input', :type => 'hidden', :name => '_method', :value => method.to_s)
|
331
|
-
end
|
288
|
+
url = options.is_a?(String) ? options : url_for(options)
|
289
|
+
remote = html_options.delete('remote')
|
332
290
|
|
333
|
-
|
291
|
+
method = html_options.delete('method').to_s
|
292
|
+
method_tag = %w{patch put delete}.include?(method) ? method_tag(method) : ''.html_safe
|
293
|
+
|
294
|
+
form_method = method == 'get' ? 'get' : 'post'
|
334
295
|
form_options = html_options.delete('form') || {}
|
335
296
|
form_options[:class] ||= html_options.delete('form_class') || 'button_to'
|
336
|
-
|
337
|
-
remote
|
338
|
-
|
339
|
-
request_token_tag = ''
|
340
|
-
if form_method == 'post' && protect_against_forgery?
|
341
|
-
request_token_tag = tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token)
|
342
|
-
end
|
297
|
+
form_options.merge!(method: form_method, action: url)
|
298
|
+
form_options.merge!("data-remote" => "true") if remote
|
343
299
|
|
344
|
-
|
345
|
-
name ||= url
|
300
|
+
request_token_tag = form_method == 'post' ? token_tag : ''
|
346
301
|
|
347
302
|
html_options = convert_options_to_data_attributes(options, html_options)
|
303
|
+
html_options['type'] = 'submit'
|
348
304
|
|
349
|
-
|
305
|
+
button = if block_given?
|
306
|
+
content_tag('button', html_options, &block)
|
307
|
+
else
|
308
|
+
html_options['value'] = name || url
|
309
|
+
tag('input', html_options)
|
310
|
+
end
|
350
311
|
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
"#{tag(:form, form_options, true)}<div>#{method_tag}#{tag("input", html_options)}#{request_token_tag}</div></form>".html_safe
|
312
|
+
inner_tags = method_tag.safe_concat(button).safe_concat(request_token_tag)
|
313
|
+
content_tag('form', content_tag('div', inner_tags), form_options)
|
355
314
|
end
|
356
315
|
|
357
|
-
|
358
316
|
# Creates a link tag of the given +name+ using a URL created by the set of
|
359
317
|
# +options+ unless the current request URI is the same as the links, in
|
360
318
|
# which case only the name is returned (or the given block is yielded, if
|
@@ -366,8 +324,8 @@ module ActionView
|
|
366
324
|
# Let's say you have a navigation menu...
|
367
325
|
#
|
368
326
|
# <ul id="navbar">
|
369
|
-
# <li><%= link_to_unless_current("Home", { :
|
370
|
-
# <li><%= link_to_unless_current("About Us", { :
|
327
|
+
# <li><%= link_to_unless_current("Home", { action: "index" }) %></li>
|
328
|
+
# <li><%= link_to_unless_current("About Us", { action: "about" }) %></li>
|
371
329
|
# </ul>
|
372
330
|
#
|
373
331
|
# If in the "about" action, it will render...
|
@@ -389,8 +347,8 @@ module ActionView
|
|
389
347
|
# "Go Back" link instead of a link to the comments page, we could do something like this...
|
390
348
|
#
|
391
349
|
# <%=
|
392
|
-
# link_to_unless_current("Comment", { :
|
393
|
-
# link_to("Go back", { :
|
350
|
+
# link_to_unless_current("Comment", { controller: "comments", action: "new" }) do
|
351
|
+
# link_to("Go back", { controller: "posts", action: "index" })
|
394
352
|
# end
|
395
353
|
# %>
|
396
354
|
def link_to_unless_current(name, options = {}, html_options = {}, &block)
|
@@ -404,13 +362,13 @@ module ActionView
|
|
404
362
|
# accepts the name or the full argument list for +link_to_unless+.
|
405
363
|
#
|
406
364
|
# ==== Examples
|
407
|
-
# <%= link_to_unless(@current_user.nil?, "Reply", { :
|
365
|
+
# <%= link_to_unless(@current_user.nil?, "Reply", { action: "reply" }) %>
|
408
366
|
# # If the user is logged in...
|
409
367
|
# # => <a href="/controller/reply/">Reply</a>
|
410
368
|
#
|
411
369
|
# <%=
|
412
|
-
# link_to_unless(@current_user.nil?, "Reply", { :
|
413
|
-
# link_to(name, { :
|
370
|
+
# link_to_unless(@current_user.nil?, "Reply", { action: "reply" }) do |name|
|
371
|
+
# link_to(name, { controller: "accounts", action: "signup" })
|
414
372
|
# end
|
415
373
|
# %>
|
416
374
|
# # If the user is logged in...
|
@@ -422,7 +380,7 @@ module ActionView
|
|
422
380
|
if block_given?
|
423
381
|
block.arity <= 1 ? capture(name, &block) : capture(name, options, html_options, &block)
|
424
382
|
else
|
425
|
-
|
383
|
+
name
|
426
384
|
end
|
427
385
|
else
|
428
386
|
link_to(name, options, html_options)
|
@@ -436,13 +394,13 @@ module ActionView
|
|
436
394
|
# in +link_to_unless+).
|
437
395
|
#
|
438
396
|
# ==== Examples
|
439
|
-
# <%= link_to_if(@current_user.nil?, "Login", { :
|
397
|
+
# <%= link_to_if(@current_user.nil?, "Login", { controller: "sessions", action: "new" }) %>
|
440
398
|
# # If the user isn't logged in...
|
441
399
|
# # => <a href="/sessions/new/">Login</a>
|
442
400
|
#
|
443
401
|
# <%=
|
444
|
-
# link_to_if(@current_user.nil?, "Login", { :
|
445
|
-
# link_to(@current_user.login, { :
|
402
|
+
# link_to_if(@current_user.nil?, "Login", { controller: "sessions", action: "new" }) do
|
403
|
+
# link_to(@current_user.login, { controller: "accounts", action: "show", id: @current_user })
|
446
404
|
# end
|
447
405
|
# %>
|
448
406
|
# # If the user isn't logged in...
|
@@ -457,132 +415,96 @@ module ActionView
|
|
457
415
|
# also used as the name of the link unless +name+ is specified. Additional
|
458
416
|
# HTML attributes for the link can be passed in +html_options+.
|
459
417
|
#
|
460
|
-
# +mail_to+ has several methods for
|
461
|
-
#
|
418
|
+
# +mail_to+ has several methods for customizing the email itself by
|
419
|
+
# passing special keys to +html_options+.
|
462
420
|
#
|
463
421
|
# ==== Options
|
464
|
-
# * <tt>:encode</tt> - This key will accept the strings "javascript" or "hex".
|
465
|
-
# Passing "javascript" will dynamically create and encode the mailto link then
|
466
|
-
# eval it into the DOM of the page. This method will not show the link on
|
467
|
-
# the page if the user has JavaScript disabled. Passing "hex" will hex
|
468
|
-
# encode the +email_address+ before outputting the mailto link.
|
469
|
-
# * <tt>:replace_at</tt> - When the link +name+ isn't provided, the
|
470
|
-
# +email_address+ is used for the link label. You can use this option to
|
471
|
-
# obfuscate the +email_address+ by substituting the @ sign with the string
|
472
|
-
# given as the value.
|
473
|
-
# * <tt>:replace_dot</tt> - When the link +name+ isn't provided, the
|
474
|
-
# +email_address+ is used for the link label. You can use this option to
|
475
|
-
# obfuscate the +email_address+ by substituting the . in the email with the
|
476
|
-
# string given as the value.
|
477
422
|
# * <tt>:subject</tt> - Preset the subject line of the email.
|
478
423
|
# * <tt>:body</tt> - Preset the body of the email.
|
479
424
|
# * <tt>:cc</tt> - Carbon Copy additional recipients on the email.
|
480
425
|
# * <tt>:bcc</tt> - Blind Carbon Copy additional recipients on the email.
|
481
426
|
#
|
427
|
+
# ==== Obfuscation
|
428
|
+
# Prior to Rails 4.0, +mail_to+ provided options for encoding the address
|
429
|
+
# in order to hinder email harvesters. To take advantage of these options,
|
430
|
+
# install the +actionview-encoded_mail_to+ gem.
|
431
|
+
#
|
482
432
|
# ==== Examples
|
483
433
|
# mail_to "me@domain.com"
|
484
434
|
# # => <a href="mailto:me@domain.com">me@domain.com</a>
|
485
435
|
#
|
486
|
-
# mail_to "me@domain.com", "My email"
|
487
|
-
# # => <
|
436
|
+
# mail_to "me@domain.com", "My email"
|
437
|
+
# # => <a href="mailto:me@domain.com">My email</a>
|
488
438
|
#
|
489
|
-
# mail_to "me@domain.com", "My email", :
|
490
|
-
#
|
491
|
-
#
|
492
|
-
# mail_to "me@domain.com", nil, :replace_at => "_at_", :replace_dot => "_dot_", :class => "email"
|
493
|
-
# # => <a href="mailto:me@domain.com" class="email">me_at_domain_dot_com</a>
|
494
|
-
#
|
495
|
-
# mail_to "me@domain.com", "My email", :cc => "ccaddress@domain.com",
|
496
|
-
# :subject => "This is an example email"
|
439
|
+
# mail_to "me@domain.com", "My email", cc: "ccaddress@domain.com",
|
440
|
+
# subject: "This is an example email"
|
497
441
|
# # => <a href="mailto:me@domain.com?cc=ccaddress@domain.com&subject=This%20is%20an%20example%20email">My email</a>
|
498
442
|
def mail_to(email_address, name = nil, html_options = {})
|
499
443
|
email_address = ERB::Util.html_escape(email_address)
|
500
444
|
|
501
|
-
html_options
|
502
|
-
encode = html_options.delete("encode").to_s
|
445
|
+
html_options.stringify_keys!
|
503
446
|
|
504
447
|
extras = %w{ cc bcc body subject }.map { |item|
|
505
448
|
option = html_options.delete(item) || next
|
506
|
-
"#{item}=#{Rack::Utils.
|
449
|
+
"#{item}=#{Rack::Utils.escape_path(option)}"
|
507
450
|
}.compact
|
508
451
|
extras = extras.empty? ? '' : '?' + ERB::Util.html_escape(extras.join('&'))
|
509
|
-
|
510
|
-
|
511
|
-
email_address_obfuscated.gsub!(/@/, html_options.delete("replace_at")) if html_options.key?("replace_at")
|
512
|
-
email_address_obfuscated.gsub!(/\./, html_options.delete("replace_dot")) if html_options.key?("replace_dot")
|
513
|
-
case encode
|
514
|
-
when "javascript"
|
515
|
-
string = ''
|
516
|
-
html = content_tag("a", name || email_address_obfuscated.html_safe, html_options.merge("href" => "mailto:#{email_address}#{extras}".html_safe))
|
517
|
-
html = escape_javascript(html.to_str)
|
518
|
-
"document.write('#{html}');".each_byte do |c|
|
519
|
-
string << sprintf("%%%x", c)
|
520
|
-
end
|
521
|
-
"<script type=\"#{Mime::JS}\">eval(decodeURIComponent('#{string}'))</script>".html_safe
|
522
|
-
when "hex"
|
523
|
-
email_address_encoded = email_address_obfuscated.unpack('C*').map {|c|
|
524
|
-
sprintf("&#%d;", c)
|
525
|
-
}.join
|
526
|
-
|
527
|
-
string = 'mailto:'.unpack('C*').map { |c|
|
528
|
-
sprintf("&#%d;", c)
|
529
|
-
}.join + email_address.unpack('C*').map { |c|
|
530
|
-
char = c.chr
|
531
|
-
char =~ /\w/ ? sprintf("%%%x", c) : char
|
532
|
-
}.join
|
533
|
-
|
534
|
-
content_tag "a", name || email_address_encoded.html_safe, html_options.merge("href" => "#{string}#{extras}".html_safe)
|
535
|
-
else
|
536
|
-
content_tag "a", name || email_address_obfuscated.html_safe, html_options.merge("href" => "mailto:#{email_address}#{extras}".html_safe)
|
537
|
-
end
|
452
|
+
|
453
|
+
content_tag "a", name || email_address.html_safe, html_options.merge("href" => "mailto:#{email_address}#{extras}".html_safe)
|
538
454
|
end
|
539
455
|
|
540
456
|
# True if the current request URI was generated by the given +options+.
|
541
457
|
#
|
542
458
|
# ==== Examples
|
543
|
-
# Let's say we're in the <tt
|
459
|
+
# Let's say we're in the <tt>http://www.example.com/shop/checkout?order=desc</tt> action.
|
544
460
|
#
|
545
|
-
# current_page?(:
|
461
|
+
# current_page?(action: 'process')
|
546
462
|
# # => false
|
547
463
|
#
|
548
|
-
# current_page?(:
|
464
|
+
# current_page?(controller: 'shop', action: 'checkout')
|
549
465
|
# # => true
|
550
466
|
#
|
551
|
-
# current_page?(:
|
467
|
+
# current_page?(controller: 'shop', action: 'checkout', order: 'asc')
|
552
468
|
# # => false
|
553
469
|
#
|
554
|
-
# current_page?(:
|
470
|
+
# current_page?(action: 'checkout')
|
555
471
|
# # => true
|
556
472
|
#
|
557
|
-
# current_page?(:
|
473
|
+
# current_page?(controller: 'library', action: 'checkout')
|
558
474
|
# # => false
|
559
475
|
#
|
560
|
-
#
|
476
|
+
# current_page?('http://www.example.com/shop/checkout')
|
477
|
+
# # => true
|
478
|
+
#
|
479
|
+
# current_page?('/shop/checkout')
|
480
|
+
# # => true
|
561
481
|
#
|
562
|
-
#
|
482
|
+
# Let's say we're in the <tt>http://www.example.com/shop/checkout?order=desc&page=1</tt> action.
|
483
|
+
#
|
484
|
+
# current_page?(action: 'process')
|
563
485
|
# # => false
|
564
486
|
#
|
565
|
-
# current_page?(:
|
487
|
+
# current_page?(controller: 'shop', action: 'checkout')
|
566
488
|
# # => true
|
567
489
|
#
|
568
|
-
# current_page?(:
|
490
|
+
# current_page?(controller: 'shop', action: 'checkout', order: 'desc', page: '1')
|
569
491
|
# # => true
|
570
492
|
#
|
571
|
-
# current_page?(:
|
493
|
+
# current_page?(controller: 'shop', action: 'checkout', order: 'desc', page: '2')
|
572
494
|
# # => false
|
573
495
|
#
|
574
|
-
# current_page?(:
|
496
|
+
# current_page?(controller: 'shop', action: 'checkout', order: 'desc')
|
575
497
|
# # => false
|
576
498
|
#
|
577
|
-
# current_page?(:
|
499
|
+
# current_page?(action: 'checkout')
|
578
500
|
# # => true
|
579
501
|
#
|
580
|
-
# current_page?(:
|
502
|
+
# current_page?(controller: 'library', action: 'checkout')
|
581
503
|
# # => false
|
582
504
|
#
|
583
|
-
# Let's say we're in the <tt
|
505
|
+
# Let's say we're in the <tt>http://www.example.com/products</tt> action with method POST in case of invalid product.
|
584
506
|
#
|
585
|
-
# current_page?(:
|
507
|
+
# current_page?(controller: 'product', action: 'index')
|
586
508
|
# # => false
|
587
509
|
#
|
588
510
|
def current_page?(options)
|
@@ -592,18 +514,14 @@ module ActionView
|
|
592
514
|
"in a #request method"
|
593
515
|
end
|
594
516
|
|
595
|
-
return false unless request.get?
|
517
|
+
return false unless request.get? || request.head?
|
596
518
|
|
597
519
|
url_string = url_for(options)
|
598
520
|
|
599
521
|
# We ignore any extra parameters in the request_uri if the
|
600
522
|
# submitted url doesn't have any either. This lets the function
|
601
523
|
# work with things like ?order=asc
|
602
|
-
|
603
|
-
request_uri = request.fullpath
|
604
|
-
else
|
605
|
-
request_uri = request.path
|
606
|
-
end
|
524
|
+
request_uri = url_string.index("?") ? request.fullpath : request.path
|
607
525
|
|
608
526
|
if url_string =~ /^\w+:\/\//
|
609
527
|
url_string == "#{request.protocol}#{request.host_with_port}#{request_uri}"
|
@@ -622,9 +540,23 @@ module ActionView
|
|
622
540
|
confirm = html_options.delete('confirm')
|
623
541
|
method = html_options.delete('method')
|
624
542
|
|
625
|
-
|
626
|
-
|
627
|
-
|
543
|
+
if confirm
|
544
|
+
message = ":confirm option is deprecated and will be removed from Rails 4.1. " \
|
545
|
+
"Use 'data: { confirm: \'Text\' }' instead."
|
546
|
+
ActiveSupport::Deprecation.warn message
|
547
|
+
|
548
|
+
html_options["data-confirm"] = confirm
|
549
|
+
end
|
550
|
+
|
551
|
+
add_method_to_attributes!(html_options, method) if method
|
552
|
+
|
553
|
+
if disable_with
|
554
|
+
message = ":disable_with option is deprecated and will be removed from Rails 4.1. " \
|
555
|
+
"Use 'data: { disable_with: \'Text\' }' instead."
|
556
|
+
ActiveSupport::Deprecation.warn message
|
557
|
+
|
558
|
+
html_options["data-disable-with"] = disable_with
|
559
|
+
end
|
628
560
|
|
629
561
|
html_options
|
630
562
|
else
|
@@ -640,27 +572,11 @@ module ActionView
|
|
640
572
|
|
641
573
|
def add_method_to_attributes!(html_options, method)
|
642
574
|
if method && method.to_s.downcase != "get" && html_options["rel"] !~ /nofollow/
|
643
|
-
html_options["rel"] = "#{html_options["rel"]} nofollow".
|
575
|
+
html_options["rel"] = "#{html_options["rel"]} nofollow".lstrip
|
644
576
|
end
|
645
577
|
html_options["data-method"] = method
|
646
578
|
end
|
647
579
|
|
648
|
-
def options_for_javascript(options)
|
649
|
-
if options.empty?
|
650
|
-
'{}'
|
651
|
-
else
|
652
|
-
"{#{options.keys.map { |k| "#{k}:#{options[k]}" }.sort.join(', ')}}"
|
653
|
-
end
|
654
|
-
end
|
655
|
-
|
656
|
-
def array_or_string_for_javascript(option)
|
657
|
-
if option.kind_of?(Array)
|
658
|
-
"['#{option.join('\',\'')}']"
|
659
|
-
elsif !option.nil?
|
660
|
-
"'#{option}'"
|
661
|
-
end
|
662
|
-
end
|
663
|
-
|
664
580
|
# Processes the +html_options+ hash, converting the boolean
|
665
581
|
# attributes from true/false form into the form required by
|
666
582
|
# HTML/XHTML. (An attribute is considered to be boolean if
|
@@ -688,6 +604,19 @@ module ActionView
|
|
688
604
|
bool_attrs.each { |x| html_options[x] = x if html_options.delete(x) }
|
689
605
|
html_options
|
690
606
|
end
|
607
|
+
|
608
|
+
def token_tag(token=nil)
|
609
|
+
if token != false && protect_against_forgery?
|
610
|
+
token ||= form_authenticity_token
|
611
|
+
tag(:input, type: "hidden", name: request_forgery_protection_token.to_s, value: token)
|
612
|
+
else
|
613
|
+
''
|
614
|
+
end
|
615
|
+
end
|
616
|
+
|
617
|
+
def method_tag(method)
|
618
|
+
tag('input', type: 'hidden', name: '_method', value: method.to_s)
|
619
|
+
end
|
691
620
|
end
|
692
621
|
end
|
693
622
|
end
|