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,38 +1,81 @@
|
|
1
1
|
module ActionDispatch
|
2
2
|
module Http
|
3
|
+
# Models uploaded files.
|
4
|
+
#
|
5
|
+
# The actual file is accessible via the +tempfile+ accessor, though some
|
6
|
+
# of its interface is available directly for convenience.
|
7
|
+
#
|
8
|
+
# Uploaded files are temporary files whose lifespan is one request. When
|
9
|
+
# the object is finalized Ruby unlinks the file, so there is not need to
|
10
|
+
# clean them with a separate maintenance task.
|
3
11
|
class UploadedFile
|
4
|
-
|
12
|
+
# The basename of the file in the client.
|
13
|
+
attr_accessor :original_filename
|
14
|
+
|
15
|
+
# A string with the MIME type of the file.
|
16
|
+
attr_accessor :content_type
|
17
|
+
|
18
|
+
# A +Tempfile+ object with the actual uploaded file. Note that some of
|
19
|
+
# its interface is available directly.
|
20
|
+
attr_accessor :tempfile
|
21
|
+
|
22
|
+
# A string with the headers of the multipart request.
|
23
|
+
attr_accessor :headers
|
24
|
+
|
25
|
+
def initialize(hash) # :nodoc:
|
26
|
+
@tempfile = hash[:tempfile]
|
27
|
+
raise(ArgumentError, ':tempfile is required') unless @tempfile
|
5
28
|
|
6
|
-
def initialize(hash)
|
7
29
|
@original_filename = encode_filename(hash[:filename])
|
8
30
|
@content_type = hash[:type]
|
9
31
|
@headers = hash[:head]
|
10
|
-
@tempfile = hash[:tempfile]
|
11
|
-
raise(ArgumentError, ':tempfile is required') unless @tempfile
|
12
32
|
end
|
13
33
|
|
14
|
-
|
15
|
-
|
34
|
+
# Shortcut for +tempfile.read+.
|
35
|
+
def read(length=nil, buffer=nil)
|
36
|
+
@tempfile.read(length, buffer)
|
16
37
|
end
|
17
38
|
|
18
|
-
#
|
19
|
-
|
20
|
-
|
39
|
+
# Shortcut for +tempfile.open+.
|
40
|
+
def open
|
41
|
+
@tempfile.open
|
42
|
+
end
|
43
|
+
|
44
|
+
# Shortcut for +tempfile.close+.
|
45
|
+
def close(unlink_now=false)
|
46
|
+
@tempfile.close(unlink_now)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Shortcut for +tempfile.path+.
|
50
|
+
def path
|
51
|
+
@tempfile.path
|
52
|
+
end
|
53
|
+
|
54
|
+
# Shortcut for +tempfile.rewind+.
|
55
|
+
def rewind
|
56
|
+
@tempfile.rewind
|
57
|
+
end
|
58
|
+
|
59
|
+
# Shortcut for +tempfile.size+.
|
60
|
+
def size
|
61
|
+
@tempfile.size
|
62
|
+
end
|
63
|
+
|
64
|
+
# Shortcut for +tempfile.eof?+.
|
65
|
+
def eof?
|
66
|
+
@tempfile.eof?
|
21
67
|
end
|
22
68
|
|
23
69
|
private
|
70
|
+
|
24
71
|
def encode_filename(filename)
|
25
|
-
# Encode the filename in the utf8 encoding, unless it is nil
|
26
|
-
|
27
|
-
filename.force_encoding("UTF-8").encode!
|
28
|
-
else
|
29
|
-
filename
|
30
|
-
end
|
72
|
+
# Encode the filename in the utf8 encoding, unless it is nil
|
73
|
+
filename.force_encoding(Encoding::UTF_8).encode! if filename
|
31
74
|
end
|
32
75
|
end
|
33
76
|
|
34
|
-
module Upload
|
35
|
-
# Convert nested Hash to HashWithIndifferentAccess and replace
|
77
|
+
module Upload # :nodoc:
|
78
|
+
# Convert nested Hash to ActiveSupport::HashWithIndifferentAccess and replace
|
36
79
|
# file upload hash with UploadedFile objects
|
37
80
|
def normalize_parameters(value)
|
38
81
|
if Hash === value && value.has_key?(:tempfile)
|
@@ -1,19 +1,26 @@
|
|
1
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
2
|
+
require 'active_support/core_ext/hash/slice'
|
3
|
+
|
1
4
|
module ActionDispatch
|
2
5
|
module Http
|
3
6
|
module URL
|
7
|
+
IP_HOST_REGEXP = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
|
8
|
+
|
4
9
|
mattr_accessor :tld_length
|
5
10
|
self.tld_length = 1
|
6
11
|
|
7
12
|
class << self
|
8
13
|
def extract_domain(host, tld_length = @@tld_length)
|
9
|
-
|
10
|
-
host.split('.').last(1 + tld_length).join('.')
|
14
|
+
host.split('.').last(1 + tld_length).join('.') if named_host?(host)
|
11
15
|
end
|
12
16
|
|
13
17
|
def extract_subdomains(host, tld_length = @@tld_length)
|
14
|
-
|
15
|
-
|
16
|
-
|
18
|
+
if named_host?(host)
|
19
|
+
parts = host.split('.')
|
20
|
+
parts[0..-(tld_length + 2)]
|
21
|
+
else
|
22
|
+
[]
|
23
|
+
end
|
17
24
|
end
|
18
25
|
|
19
26
|
def extract_subdomain(host, tld_length = @@tld_length)
|
@@ -21,42 +28,51 @@ module ActionDispatch
|
|
21
28
|
end
|
22
29
|
|
23
30
|
def url_for(options = {})
|
24
|
-
|
31
|
+
path = options.delete(:script_name).to_s.chomp("/")
|
32
|
+
path << options.delete(:path).to_s
|
33
|
+
|
34
|
+
params = options[:params].is_a?(Hash) ? options[:params] : options.slice(:params)
|
35
|
+
params.reject! { |_,v| v.to_param.nil? }
|
36
|
+
|
37
|
+
result = build_host_url(options)
|
38
|
+
if options[:trailing_slash]
|
39
|
+
if path.include?('?')
|
40
|
+
result << path.sub(/\?/, '/\&')
|
41
|
+
else
|
42
|
+
result << path.sub(/[^\/]\z|\A\z/, '\&/')
|
43
|
+
end
|
44
|
+
else
|
45
|
+
result << path
|
46
|
+
end
|
47
|
+
result << "?#{params.to_query}" unless params.empty?
|
48
|
+
result << "##{Journey::Router::Utils.escape_fragment(options[:anchor].to_param.to_s)}" if options[:anchor]
|
49
|
+
result
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def build_host_url(options)
|
55
|
+
if options[:host].blank? && options[:only_path].blank?
|
25
56
|
raise ArgumentError, 'Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true'
|
26
57
|
end
|
27
58
|
|
28
|
-
|
59
|
+
result = ""
|
29
60
|
|
30
61
|
unless options[:only_path]
|
31
62
|
unless options[:protocol] == false
|
32
|
-
|
33
|
-
|
63
|
+
result << (options[:protocol] || "http")
|
64
|
+
result << ":" unless result.match(%r{:|//})
|
34
65
|
end
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
path = options.delete(:path) || ''
|
42
|
-
|
43
|
-
params = options[:params] || {}
|
44
|
-
params.reject! {|k,v| v.to_param.nil? }
|
45
|
-
|
46
|
-
if options[:trailing_slash] && !path.ends_with?('/')
|
47
|
-
rewritten_url << path.sub(/(\?|\z)/) { "/" + $& }
|
48
|
-
else
|
49
|
-
rewritten_url << path
|
66
|
+
result << "//" unless result.match("//")
|
67
|
+
result << rewrite_authentication(options)
|
68
|
+
result << host_or_subdomain_and_domain(options)
|
69
|
+
result << ":#{options.delete(:port)}" if options[:port]
|
50
70
|
end
|
51
|
-
|
52
|
-
rewritten_url << "##{Journey::Router::Utils.escape_fragment(options[:anchor].to_param.to_s)}" if options[:anchor]
|
53
|
-
rewritten_url
|
71
|
+
result
|
54
72
|
end
|
55
73
|
|
56
|
-
private
|
57
|
-
|
58
74
|
def named_host?(host)
|
59
|
-
|
75
|
+
host && IP_HOST_REGEXP !~ host
|
60
76
|
end
|
61
77
|
|
62
78
|
def rewrite_authentication(options)
|
@@ -82,6 +98,12 @@ module ActionDispatch
|
|
82
98
|
end
|
83
99
|
end
|
84
100
|
|
101
|
+
def initialize(env)
|
102
|
+
super
|
103
|
+
@protocol = nil
|
104
|
+
@port = nil
|
105
|
+
end
|
106
|
+
|
85
107
|
# Returns the complete URL used for this request.
|
86
108
|
def url
|
87
109
|
protocol + host_with_port + fullpath
|
@@ -171,7 +193,7 @@ module ActionDispatch
|
|
171
193
|
# such as 2 to catch <tt>"www"</tt> instead of <tt>"www.rubyonrails"</tt>
|
172
194
|
# in "www.rubyonrails.co.uk".
|
173
195
|
def subdomain(tld_length = @@tld_length)
|
174
|
-
|
196
|
+
ActionDispatch::Http::URL.extract_subdomain(host, tld_length)
|
175
197
|
end
|
176
198
|
end
|
177
199
|
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require 'action_controller/metal/exceptions'
|
2
|
+
|
3
|
+
module ActionDispatch
|
4
|
+
module Journey
|
5
|
+
# The Formatter class is used for formatting URLs. For example, parameters
|
6
|
+
# passed to +url_for+ in rails will eventually call Formatter#generate.
|
7
|
+
class Formatter # :nodoc:
|
8
|
+
attr_reader :routes
|
9
|
+
|
10
|
+
def initialize(routes)
|
11
|
+
@routes = routes
|
12
|
+
@cache = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def generate(type, name, options, recall = {}, parameterize = nil)
|
16
|
+
constraints = recall.merge(options)
|
17
|
+
missing_keys = []
|
18
|
+
|
19
|
+
match_route(name, constraints) do |route|
|
20
|
+
parameterized_parts = extract_parameterized_parts(route, options, recall, parameterize)
|
21
|
+
next if !name && route.requirements.empty? && route.parts.empty?
|
22
|
+
|
23
|
+
missing_keys = missing_keys(route, parameterized_parts)
|
24
|
+
next unless missing_keys.empty?
|
25
|
+
params = options.dup.delete_if do |key, _|
|
26
|
+
parameterized_parts.key?(key) || route.defaults.key?(key)
|
27
|
+
end
|
28
|
+
|
29
|
+
return [route.format(parameterized_parts), params]
|
30
|
+
end
|
31
|
+
|
32
|
+
message = "No route matches #{constraints.inspect}"
|
33
|
+
message << " missing required keys: #{missing_keys.inspect}" if name
|
34
|
+
|
35
|
+
raise ActionController::UrlGenerationError, message
|
36
|
+
end
|
37
|
+
|
38
|
+
def clear
|
39
|
+
@cache = nil
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def extract_parameterized_parts(route, options, recall, parameterize = nil)
|
45
|
+
parameterized_parts = recall.merge(options)
|
46
|
+
|
47
|
+
keys_to_keep = route.parts.reverse.drop_while { |part|
|
48
|
+
!options.key?(part) || (options[part] || recall[part]).nil?
|
49
|
+
} | route.required_parts
|
50
|
+
|
51
|
+
(parameterized_parts.keys - keys_to_keep).each do |bad_key|
|
52
|
+
parameterized_parts.delete(bad_key)
|
53
|
+
end
|
54
|
+
|
55
|
+
if parameterize
|
56
|
+
parameterized_parts.each do |k, v|
|
57
|
+
parameterized_parts[k] = parameterize.call(k, v)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
parameterized_parts.keep_if { |_, v| v }
|
62
|
+
parameterized_parts
|
63
|
+
end
|
64
|
+
|
65
|
+
def named_routes
|
66
|
+
routes.named_routes
|
67
|
+
end
|
68
|
+
|
69
|
+
def match_route(name, options)
|
70
|
+
if named_routes.key?(name)
|
71
|
+
yield named_routes[name]
|
72
|
+
else
|
73
|
+
routes = non_recursive(cache, options.to_a)
|
74
|
+
|
75
|
+
hash = routes.group_by { |_, r| r.score(options) }
|
76
|
+
|
77
|
+
hash.keys.sort.reverse_each do |score|
|
78
|
+
next if score < 0
|
79
|
+
|
80
|
+
hash[score].sort_by { |i, _| i }.each do |_, route|
|
81
|
+
yield route
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def non_recursive(cache, options)
|
88
|
+
routes = []
|
89
|
+
stack = [cache]
|
90
|
+
|
91
|
+
while stack.any?
|
92
|
+
c = stack.shift
|
93
|
+
routes.concat(c[:___routes]) if c.key?(:___routes)
|
94
|
+
|
95
|
+
options.each do |pair|
|
96
|
+
stack << c[pair] if c.key?(pair)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
routes
|
101
|
+
end
|
102
|
+
|
103
|
+
# Returns an array populated with missing keys if any are present.
|
104
|
+
def missing_keys(route, parts)
|
105
|
+
missing_keys = []
|
106
|
+
tests = route.path.requirements
|
107
|
+
route.required_parts.each { |key|
|
108
|
+
if tests.key?(key)
|
109
|
+
missing_keys << key unless /\A#{tests[key]}\Z/ === parts[key]
|
110
|
+
else
|
111
|
+
missing_keys << key unless parts[key]
|
112
|
+
end
|
113
|
+
}
|
114
|
+
missing_keys
|
115
|
+
end
|
116
|
+
|
117
|
+
def possibles(cache, options, depth = 0)
|
118
|
+
cache.fetch(:___routes) { [] } + options.find_all { |pair|
|
119
|
+
cache.key?(pair)
|
120
|
+
}.map { |pair|
|
121
|
+
possibles(cache[pair], options, depth + 1)
|
122
|
+
}.flatten(1)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Returns +true+ if no missing keys are present, otherwise +false+.
|
126
|
+
def verify_required_parts!(route, parts)
|
127
|
+
missing_keys(route, parts).empty?
|
128
|
+
end
|
129
|
+
|
130
|
+
def build_cache
|
131
|
+
root = { ___routes: [] }
|
132
|
+
routes.each_with_index do |route, i|
|
133
|
+
leaf = route.required_defaults.inject(root) do |h, tuple|
|
134
|
+
h[tuple] ||= {}
|
135
|
+
end
|
136
|
+
(leaf[:___routes] ||= []) << [i, route]
|
137
|
+
end
|
138
|
+
root
|
139
|
+
end
|
140
|
+
|
141
|
+
def cache
|
142
|
+
@cache ||= build_cache
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'action_dispatch/journey/gtg/transition_table'
|
2
|
+
|
3
|
+
module ActionDispatch
|
4
|
+
module Journey # :nodoc:
|
5
|
+
module GTG # :nodoc:
|
6
|
+
class Builder # :nodoc:
|
7
|
+
DUMMY = Nodes::Dummy.new
|
8
|
+
|
9
|
+
attr_reader :root, :ast, :endpoints
|
10
|
+
|
11
|
+
def initialize(root)
|
12
|
+
@root = root
|
13
|
+
@ast = Nodes::Cat.new root, DUMMY
|
14
|
+
@followpos = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def transition_table
|
18
|
+
dtrans = TransitionTable.new
|
19
|
+
marked = {}
|
20
|
+
state_id = Hash.new { |h,k| h[k] = h.length }
|
21
|
+
|
22
|
+
start = firstpos(root)
|
23
|
+
dstates = [start]
|
24
|
+
until dstates.empty?
|
25
|
+
s = dstates.shift
|
26
|
+
next if marked[s]
|
27
|
+
marked[s] = true # mark s
|
28
|
+
|
29
|
+
s.group_by { |state| symbol(state) }.each do |sym, ps|
|
30
|
+
u = ps.map { |l| followpos(l) }.flatten
|
31
|
+
next if u.empty?
|
32
|
+
|
33
|
+
if u.uniq == [DUMMY]
|
34
|
+
from = state_id[s]
|
35
|
+
to = state_id[Object.new]
|
36
|
+
dtrans[from, to] = sym
|
37
|
+
|
38
|
+
dtrans.add_accepting(to)
|
39
|
+
ps.each { |state| dtrans.add_memo(to, state.memo) }
|
40
|
+
else
|
41
|
+
dtrans[state_id[s], state_id[u]] = sym
|
42
|
+
|
43
|
+
if u.include?(DUMMY)
|
44
|
+
to = state_id[u]
|
45
|
+
|
46
|
+
accepting = ps.find_all { |l| followpos(l).include?(DUMMY) }
|
47
|
+
|
48
|
+
accepting.each { |accepting_state|
|
49
|
+
dtrans.add_memo(to, accepting_state.memo)
|
50
|
+
}
|
51
|
+
|
52
|
+
dtrans.add_accepting(state_id[u])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
dstates << u
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
dtrans
|
61
|
+
end
|
62
|
+
|
63
|
+
def nullable?(node)
|
64
|
+
case node
|
65
|
+
when Nodes::Group
|
66
|
+
true
|
67
|
+
when Nodes::Star
|
68
|
+
true
|
69
|
+
when Nodes::Or
|
70
|
+
node.children.any? { |c| nullable?(c) }
|
71
|
+
when Nodes::Cat
|
72
|
+
nullable?(node.left) && nullable?(node.right)
|
73
|
+
when Nodes::Terminal
|
74
|
+
!node.left
|
75
|
+
when Nodes::Unary
|
76
|
+
nullable?(node.left)
|
77
|
+
else
|
78
|
+
raise ArgumentError, 'unknown nullable: %s' % node.class.name
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def firstpos(node)
|
83
|
+
case node
|
84
|
+
when Nodes::Star
|
85
|
+
firstpos(node.left)
|
86
|
+
when Nodes::Cat
|
87
|
+
if nullable?(node.left)
|
88
|
+
firstpos(node.left) | firstpos(node.right)
|
89
|
+
else
|
90
|
+
firstpos(node.left)
|
91
|
+
end
|
92
|
+
when Nodes::Or
|
93
|
+
node.children.map { |c| firstpos(c) }.flatten.uniq
|
94
|
+
when Nodes::Unary
|
95
|
+
firstpos(node.left)
|
96
|
+
when Nodes::Terminal
|
97
|
+
nullable?(node) ? [] : [node]
|
98
|
+
else
|
99
|
+
raise ArgumentError, 'unknown firstpos: %s' % node.class.name
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def lastpos(node)
|
104
|
+
case node
|
105
|
+
when Nodes::Star
|
106
|
+
firstpos(node.left)
|
107
|
+
when Nodes::Or
|
108
|
+
node.children.map { |c| lastpos(c) }.flatten.uniq
|
109
|
+
when Nodes::Cat
|
110
|
+
if nullable?(node.right)
|
111
|
+
lastpos(node.left) | lastpos(node.right)
|
112
|
+
else
|
113
|
+
lastpos(node.right)
|
114
|
+
end
|
115
|
+
when Nodes::Terminal
|
116
|
+
nullable?(node) ? [] : [node]
|
117
|
+
when Nodes::Unary
|
118
|
+
lastpos(node.left)
|
119
|
+
else
|
120
|
+
raise ArgumentError, 'unknown lastpos: %s' % node.class.name
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def followpos(node)
|
125
|
+
followpos_table[node]
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
def followpos_table
|
131
|
+
@followpos ||= build_followpos
|
132
|
+
end
|
133
|
+
|
134
|
+
def build_followpos
|
135
|
+
table = Hash.new { |h, k| h[k] = [] }
|
136
|
+
@ast.each do |n|
|
137
|
+
case n
|
138
|
+
when Nodes::Cat
|
139
|
+
lastpos(n.left).each do |i|
|
140
|
+
table[i] += firstpos(n.right)
|
141
|
+
end
|
142
|
+
when Nodes::Star
|
143
|
+
lastpos(n).each do |i|
|
144
|
+
table[i] += firstpos(n)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
table
|
149
|
+
end
|
150
|
+
|
151
|
+
def symbol(edge)
|
152
|
+
case edge
|
153
|
+
when Journey::Nodes::Symbol
|
154
|
+
edge.regexp
|
155
|
+
else
|
156
|
+
edge.left
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|