roda 2.29.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +52 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +51 -109
- data/Rakefile +7 -14
- data/doc/conventions.rdoc +4 -4
- data/doc/release_notes/1.2.0.txt +1 -1
- data/doc/release_notes/3.0.0.txt +84 -0
- data/lib/roda.rb +25 -79
- data/lib/roda/plugins/assets.rb +25 -58
- data/lib/roda/plugins/assets_preloading.rb +0 -5
- data/lib/roda/plugins/backtracking_array.rb +0 -5
- data/lib/roda/plugins/branch_locals.rb +3 -3
- data/lib/roda/plugins/caching.rb +5 -38
- data/lib/roda/plugins/chunked.rb +7 -25
- data/lib/roda/plugins/class_level_routing.rb +2 -2
- data/lib/roda/plugins/content_for.rb +7 -10
- data/lib/roda/plugins/cookies.rb +3 -3
- data/lib/roda/plugins/csrf.rb +2 -2
- data/lib/roda/plugins/delegate.rb +3 -3
- data/lib/roda/plugins/drop_body.rb +0 -7
- data/lib/roda/plugins/empty_root.rb +0 -3
- data/lib/roda/plugins/error_email.rb +4 -6
- data/lib/roda/plugins/error_handler.rb +1 -2
- data/lib/roda/plugins/error_mail.rb +3 -6
- data/lib/roda/plugins/flash.rb +0 -4
- data/lib/roda/plugins/h.rb +5 -0
- data/lib/roda/plugins/hash_matcher.rb +4 -2
- data/lib/roda/plugins/head.rb +5 -7
- data/lib/roda/plugins/header_matchers.rb +12 -33
- data/lib/roda/plugins/heartbeat.rb +2 -7
- data/lib/roda/plugins/indifferent_params.rb +2 -2
- data/lib/roda/plugins/json.rb +6 -14
- data/lib/roda/plugins/json_parser.rb +2 -13
- data/lib/roda/plugins/mailer.rb +29 -39
- data/lib/roda/plugins/match_affix.rb +0 -5
- data/lib/roda/plugins/middleware.rb +10 -15
- data/lib/roda/plugins/multi_route.rb +8 -5
- data/lib/roda/plugins/multi_run.rb +1 -0
- data/lib/roda/plugins/named_templates.rb +2 -2
- data/lib/roda/plugins/optimized_string_matchers.rb +0 -3
- data/lib/roda/plugins/padrino_render.rb +6 -9
- data/lib/roda/plugins/param_matchers.rb +6 -6
- data/lib/roda/plugins/params_capturing.rb +15 -35
- data/lib/roda/plugins/partials.rb +3 -8
- data/lib/roda/plugins/path.rb +5 -5
- data/lib/roda/plugins/path_matchers.rb +3 -3
- data/lib/roda/plugins/path_rewriter.rb +4 -9
- data/lib/roda/plugins/placeholder_string_matchers.rb +1 -1
- data/lib/roda/plugins/precompile_templates.rb +10 -20
- data/lib/roda/plugins/public.rb +6 -9
- data/lib/roda/plugins/render.rb +50 -171
- data/lib/roda/plugins/render_each.rb +4 -7
- data/lib/roda/plugins/render_locals.rb +6 -20
- data/lib/roda/plugins/request_headers.rb +2 -4
- data/lib/roda/plugins/run_append_slash.rb +1 -4
- data/lib/roda/plugins/run_handler.rb +4 -7
- data/lib/roda/plugins/shared_vars.rb +3 -6
- data/lib/roda/plugins/sinatra_helpers.rb +11 -40
- data/lib/roda/plugins/slash_path_empty.rb +0 -3
- data/lib/roda/plugins/static.rb +2 -2
- data/lib/roda/plugins/static_routing.rb +2 -3
- data/lib/roda/plugins/streaming.rb +15 -108
- data/lib/roda/plugins/strip_path_prefix.rb +1 -1
- data/lib/roda/plugins/symbol_matchers.rb +7 -23
- data/lib/roda/plugins/type_routing.rb +4 -9
- data/lib/roda/plugins/view_options.rb +10 -66
- data/lib/roda/version.rb +2 -2
- data/spec/all.rb +0 -2
- data/spec/composition_spec.rb +1 -1
- data/spec/env_spec.rb +1 -1
- data/spec/freeze_spec.rb +1 -1
- data/spec/integration_spec.rb +1 -1
- data/spec/matchers_spec.rb +26 -70
- data/spec/opts_spec.rb +1 -1
- data/spec/plugin/all_verbs_spec.rb +1 -1
- data/spec/plugin/assets_preloading_spec.rb +1 -1
- data/spec/plugin/assets_spec.rb +43 -27
- data/spec/plugin/backtracking_array_spec.rb +1 -1
- data/spec/plugin/branch_locals_spec.rb +1 -1
- data/spec/plugin/caching_spec.rb +1 -1
- data/spec/plugin/chunked_spec.rb +1 -1
- data/spec/plugin/class_level_routing_spec.rb +1 -1
- data/spec/plugin/class_matchers_spec.rb +1 -1
- data/spec/plugin/content_for_spec.rb +2 -7
- data/spec/plugin/cookies_spec.rb +1 -1
- data/spec/plugin/csrf_spec.rb +1 -1
- data/spec/plugin/default_headers_spec.rb +1 -1
- data/spec/plugin/default_status_spec.rb +1 -1
- data/spec/plugin/delay_build_spec.rb +1 -1
- data/spec/plugin/delegate_spec.rb +1 -1
- data/spec/plugin/delete_empty_headers_spec.rb +1 -1
- data/spec/plugin/disallow_file_uploads_spec.rb +2 -2
- data/spec/plugin/drop_body_spec.rb +1 -1
- data/spec/plugin/empty_root_spec.rb +1 -1
- data/spec/plugin/environments_spec.rb +1 -1
- data/spec/plugin/error_email_spec.rb +1 -1
- data/spec/plugin/error_handler_spec.rb +1 -1
- data/spec/plugin/error_mail_spec.rb +2 -2
- data/spec/plugin/flash_spec.rb +1 -1
- data/spec/plugin/h_spec.rb +1 -1
- data/spec/plugin/halt_spec.rb +2 -2
- data/spec/plugin/hash_matcher_spec.rb +1 -1
- data/spec/plugin/head_spec.rb +1 -1
- data/spec/plugin/header_matchers_spec.rb +4 -47
- data/spec/plugin/heartbeat_spec.rb +1 -1
- data/spec/plugin/hooks_spec.rb +1 -1
- data/spec/plugin/indifferent_params_spec.rb +1 -1
- data/spec/plugin/json_parser_spec.rb +12 -1
- data/spec/plugin/json_spec.rb +8 -1
- data/spec/plugin/mailer_spec.rb +1 -1
- data/spec/plugin/match_affix_spec.rb +1 -1
- data/spec/plugin/middleware_spec.rb +15 -1
- data/spec/plugin/module_include_spec.rb +1 -1
- data/spec/plugin/multi_route_spec.rb +5 -3
- data/spec/plugin/multi_run_spec.rb +1 -1
- data/spec/plugin/multi_view_spec.rb +1 -1
- data/spec/plugin/named_templates_spec.rb +1 -1
- data/spec/plugin/not_allowed_spec.rb +1 -1
- data/spec/plugin/not_found_spec.rb +1 -1
- data/spec/plugin/optimized_string_matchers_spec.rb +1 -1
- data/spec/plugin/padrino_render_spec.rb +1 -1
- data/spec/plugin/param_matchers_spec.rb +1 -1
- data/spec/plugin/params_capturing_spec.rb +6 -22
- data/spec/plugin/partials_spec.rb +1 -1
- data/spec/plugin/pass_spec.rb +1 -1
- data/spec/plugin/path_matchers_spec.rb +1 -1
- data/spec/plugin/path_rewriter_spec.rb +1 -1
- data/spec/plugin/path_spec.rb +1 -1
- data/spec/plugin/placeholder_string_matchers_spec.rb +3 -36
- data/spec/plugin/precompile_templates_spec.rb +1 -17
- data/spec/plugin/public_spec.rb +3 -4
- data/spec/plugin/render_each_spec.rb +1 -1
- data/spec/plugin/render_locals_spec.rb +1 -1
- data/spec/plugin/render_spec.rb +28 -114
- data/spec/plugin/request_headers_spec.rb +1 -1
- data/spec/plugin/response_request_spec.rb +1 -1
- data/spec/plugin/run_append_slash_spec.rb +1 -1
- data/spec/plugin/run_handler_spec.rb +1 -1
- data/spec/plugin/shared_vars_spec.rb +1 -1
- data/spec/plugin/sinatra_helpers_spec.rb +1 -1
- data/spec/plugin/slash_path_empty_spec.rb +1 -1
- data/spec/plugin/static_routing_spec.rb +1 -1
- data/spec/plugin/static_spec.rb +1 -1
- data/spec/plugin/status_303_spec.rb +1 -1
- data/spec/plugin/status_handler_spec.rb +1 -1
- data/spec/plugin/streaming_spec.rb +1 -106
- data/spec/plugin/strip_path_prefix_spec.rb +1 -1
- data/spec/plugin/symbol_matchers_spec.rb +1 -77
- data/spec/plugin/symbol_status_spec.rb +1 -1
- data/spec/plugin/symbol_views_spec.rb +1 -1
- data/spec/plugin/type_routing_spec.rb +1 -1
- data/spec/plugin/unescape_path_spec.rb +1 -1
- data/spec/plugin/view_options_spec.rb +16 -110
- data/spec/plugin_spec.rb +1 -1
- data/spec/redirect_spec.rb +1 -1
- data/spec/request_spec.rb +1 -1
- data/spec/response_spec.rb +1 -1
- data/spec/session_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -3
- data/spec/version_spec.rb +1 -1
- metadata +6 -26
- data/lib/roda/plugins/_erubis_escaping.rb +0 -59
- data/lib/roda/plugins/per_thread_caching.rb +0 -71
- data/lib/roda/plugins/static_path_info.rb +0 -12
- data/lib/roda/plugins/view_subdirs.rb +0 -7
- data/lib/roda/plugins/websockets.rb +0 -107
- data/spec/plugin/_erubis_escaping_spec.rb +0 -97
- data/spec/plugin/per_thread_caching_spec.rb +0 -28
- data/spec/plugin/websockets_spec.rb +0 -84
data/lib/roda/plugins/h.rb
CHANGED
@@ -17,8 +17,10 @@ class Roda
|
|
17
17
|
begin
|
18
18
|
require 'cgi/escape'
|
19
19
|
unless CGI.respond_to?(:escapeHTML) # work around for JRuby 9.1
|
20
|
+
# :nocov:
|
20
21
|
CGI = Object.new
|
21
22
|
CGI.extend(defined?(::CGI::Escape) ? ::CGI::Escape : ::CGI::Util)
|
23
|
+
# :nocov:
|
22
24
|
end
|
23
25
|
|
24
26
|
module InstanceMethods
|
@@ -28,6 +30,8 @@ class Roda
|
|
28
30
|
end
|
29
31
|
end
|
30
32
|
rescue LoadError
|
33
|
+
# :nocov:
|
34
|
+
|
31
35
|
# A Hash of entities and their escaped equivalents,
|
32
36
|
# to be escaped by h().
|
33
37
|
ESCAPE_HTML = {
|
@@ -46,6 +50,7 @@ class Roda
|
|
46
50
|
string.to_s.gsub(ESCAPE_HTML_PATTERN){|c| ESCAPE_HTML[c] }
|
47
51
|
end
|
48
52
|
end
|
53
|
+
# :nocov:
|
49
54
|
end
|
50
55
|
end
|
51
56
|
|
@@ -12,7 +12,7 @@ class Roda
|
|
12
12
|
# end
|
13
13
|
#
|
14
14
|
# route do
|
15
|
-
# r.on :
|
15
|
+
# r.on foo: 'bar' do
|
16
16
|
# # matches when param foo has value bar
|
17
17
|
# end
|
18
18
|
# end
|
@@ -25,7 +25,9 @@ class Roda
|
|
25
25
|
# match, and anything else to match. See the HashMatcher module
|
26
26
|
# documentation for an example.
|
27
27
|
def hash_matcher(key, &block)
|
28
|
-
|
28
|
+
meth = :"match_#{key}"
|
29
|
+
self::RodaRequest.send(:define_method, meth, &block)
|
30
|
+
self::RodaRequest.send(:private, meth)
|
29
31
|
end
|
30
32
|
end
|
31
33
|
end
|
data/lib/roda/plugins/head.rb
CHANGED
@@ -18,7 +18,7 @@ class Roda
|
|
18
18
|
# 'a'
|
19
19
|
# end
|
20
20
|
#
|
21
|
-
# r.is 'b', :
|
21
|
+
# r.is 'b', method: [:get, :post] do
|
22
22
|
# 'b'
|
23
23
|
# end
|
24
24
|
# end
|
@@ -31,21 +31,19 @@ class Roda
|
|
31
31
|
# header options, then HEAD will be as well.
|
32
32
|
#
|
33
33
|
# NOTE: if you have a public facing website it is recommended that
|
34
|
-
# you enable this plugin
|
34
|
+
# you enable this plugin, or manually handle HEAD anywhere you would
|
35
|
+
# handle GET. Search engines and other bots may send a
|
35
36
|
# HEAD request prior to crawling a page with a GET request. Without
|
36
37
|
# this plugin those HEAD requests will return a 404 status, which
|
37
|
-
# may prevent search
|
38
|
+
# may prevent search engines from crawling your website.
|
38
39
|
module Head
|
39
|
-
EMPTY_ARRAY = [].freeze
|
40
|
-
RodaPlugins.deprecate_constant(self, :EMPTY_ARRAY)
|
41
|
-
|
42
40
|
module InstanceMethods
|
43
41
|
# Always use an empty response body for head requests, with a
|
44
42
|
# content length of 0.
|
45
43
|
def call(*)
|
46
44
|
res = super
|
47
45
|
if @_request.head?
|
48
|
-
res[2] =
|
46
|
+
res[2] = EMPTY_ARRAY
|
49
47
|
end
|
50
48
|
res
|
51
49
|
end
|
@@ -9,46 +9,34 @@ class Roda
|
|
9
9
|
# plugin :header_matchers
|
10
10
|
#
|
11
11
|
# It adds a +:header+ matcher for matching on arbitrary headers, which matches
|
12
|
-
# if the header is present:
|
12
|
+
# if the header is present, and yields the header value:
|
13
13
|
#
|
14
|
-
# r.on :
|
15
|
-
# # Looks for env['HTTP_X_APP_TOKEN']
|
16
|
-
# end
|
17
|
-
#
|
18
|
-
# For backwards compatibility, the header value is not automatically prefixed
|
19
|
-
# with HTTP_. You can set the +:header_matcher_prefix+ option for the application,
|
20
|
-
# which will automatically prefix the header with HTTP_:
|
21
|
-
#
|
22
|
-
# r.on :header=>'X-App-Token' do |header_value|
|
23
|
-
# # Looks for env['HTTP_X_APP_TOKEN']
|
14
|
+
# r.on header: 'HTTP-X-App-Token' do |header_value|
|
15
|
+
# # Looks for env['HTTP_X_APP_TOKEN'] and yields it
|
24
16
|
# end
|
25
17
|
#
|
26
18
|
# It adds a +:host+ matcher for matching by the host of the request:
|
27
19
|
#
|
28
|
-
# r.on :
|
29
|
-
# end
|
30
|
-
# r.on :host=>/\A\w+.example.com\z/ do
|
20
|
+
# r.on host: 'foo.example.com' do
|
31
21
|
# end
|
32
22
|
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
# r.on :host=>/\A(\w+).example.com\z/ do |subdomain|
|
23
|
+
# For regexp values of the +:host+ matcher, any captures are yielded to the block:
|
24
|
+
#
|
25
|
+
# r.on host: /\A(\w+).example.com\z/ do |subdomain|
|
38
26
|
# end
|
39
27
|
#
|
40
28
|
# It adds a +:user_agent+ matcher for matching on a user agent patterns, which
|
41
29
|
# yields the regexp captures to the block:
|
42
30
|
#
|
43
|
-
# r.on :
|
31
|
+
# r.on user_agent: /Chrome\/([.\d]+)/ do |chrome_version|
|
44
32
|
# end
|
45
33
|
#
|
46
34
|
# It adds an +:accept+ matcher for matching based on the Accept header:
|
47
35
|
#
|
48
|
-
# r.on :
|
36
|
+
# r.on accept: 'text/csv' do
|
49
37
|
# end
|
50
38
|
#
|
51
|
-
# Note that the accept matcher is very simple and cannot handle wildcards,
|
39
|
+
# Note that the +:accept+ matcher is very simple and cannot handle wildcards,
|
52
40
|
# priorities, or anything but a simple comma separated list of mime types.
|
53
41
|
module HeaderMatchers
|
54
42
|
module RequestMethods
|
@@ -63,15 +51,7 @@ class Roda
|
|
63
51
|
|
64
52
|
# Match if the given uppercase key is present inside the environment.
|
65
53
|
def match_header(key)
|
66
|
-
|
67
|
-
|
68
|
-
if roda_class.opts[:header_matcher_prefix]
|
69
|
-
key = "HTTP_#{key}"
|
70
|
-
else
|
71
|
-
RodaPlugins.warn ":header matcher used without :header_matcher_prefix app option. Currently this looks for the #{key} header, but in Roda 3 it will look for the HTTP_#{key} header. You should set the :header_matcher_prefix app option and update your code if necessary to avoid this deprecation warning."
|
72
|
-
end
|
73
|
-
|
74
|
-
if v = @env[key]
|
54
|
+
if v = @env["HTTP_#{key.upcase.tr("-","_")}"]
|
75
55
|
@captures << v
|
76
56
|
end
|
77
57
|
end
|
@@ -79,12 +59,11 @@ class Roda
|
|
79
59
|
# Match if the host of the request is the same as the hostname. +hostname+
|
80
60
|
# can be a regexp or a string.
|
81
61
|
def match_host(hostname)
|
82
|
-
if hostname.is_a?(Regexp)
|
62
|
+
if hostname.is_a?(Regexp)
|
83
63
|
if match = hostname.match(host)
|
84
64
|
@captures.concat(match.captures)
|
85
65
|
end
|
86
66
|
else
|
87
|
-
RodaPlugins.warn ":host matcher used with regexp value without :host_matcher_captures app option, no capturing will be done. Starting in Roda 3, the :host matcher will automatically capture if the value is a Regexp. Set :host_matcher_captures app option to enable capturing." if hostname.is_a?(Regexp)
|
88
67
|
hostname === host
|
89
68
|
end
|
90
69
|
end
|
@@ -12,17 +12,12 @@ class Roda
|
|
12
12
|
#
|
13
13
|
# You can also specify a custom heartbeat path:
|
14
14
|
#
|
15
|
-
# plugin :heartbeat, :
|
15
|
+
# plugin :heartbeat, path: '/status'
|
16
16
|
module Heartbeat
|
17
17
|
HEARTBEAT_RESPONSE = [200, {'Content-Type'=>'text/plain'}.freeze, ['OK'.freeze].freeze].freeze
|
18
18
|
|
19
|
-
OPTS = {}.freeze
|
20
|
-
RodaPlugins.deprecate_constant(self, :OPTS)
|
21
|
-
PATH_INFO = 'PATH_INFO'.freeze
|
22
|
-
RodaPlugins.deprecate_constant(self, :PATH_INFO)
|
23
|
-
|
24
19
|
# Set the heartbeat path to the given path.
|
25
|
-
def self.configure(app, opts=
|
20
|
+
def self.configure(app, opts=OPTS)
|
26
21
|
app.opts[:heartbeat_path] = (opts[:path] || app.opts[:heartbeat_path] || "/heartbeat").dup.freeze
|
27
22
|
end
|
28
23
|
|
@@ -35,7 +35,6 @@ class Roda
|
|
35
35
|
INDIFFERENT_PROC = lambda{|h,k| h[k.to_s] if k.is_a?(Symbol)}
|
36
36
|
|
37
37
|
if Rack.release > '2'
|
38
|
-
# :nocov:
|
39
38
|
class QueryParser < Rack::QueryParser
|
40
39
|
# Work around for invalid optimization in rack
|
41
40
|
def parse_nested_query(qs, d=nil)
|
@@ -66,8 +65,8 @@ class Roda
|
|
66
65
|
@_request.params
|
67
66
|
end
|
68
67
|
end
|
69
|
-
# :nocov:
|
70
68
|
else
|
69
|
+
# :nocov:
|
71
70
|
module InstanceMethods
|
72
71
|
# A copy of the request params that will automatically
|
73
72
|
# convert symbols to strings.
|
@@ -93,6 +92,7 @@ class Roda
|
|
93
92
|
end
|
94
93
|
end
|
95
94
|
end
|
95
|
+
# :nocov:
|
96
96
|
end
|
97
97
|
end
|
98
98
|
|
data/lib/roda/plugins/json.rb
CHANGED
@@ -33,35 +33,30 @@ class Roda
|
|
33
33
|
# can specifically set the allowed classes to json by adding
|
34
34
|
# using the :classes option when loading the plugin:
|
35
35
|
#
|
36
|
-
# plugin :json, :
|
36
|
+
# plugin :json, classes: [Array, Hash, Sequel::Model]
|
37
37
|
#
|
38
38
|
# By default objects are serialized with +to_json+, but you
|
39
39
|
# can pass in a custom serializer, which can be any object
|
40
40
|
# that responds to +call(object)+.
|
41
41
|
#
|
42
|
-
# plugin :json, :
|
42
|
+
# plugin :json, serializer: proc{|o| o.to_json(root: true)}
|
43
43
|
#
|
44
44
|
# If you need the request information during serialization, such
|
45
45
|
# as HTTP headers or query parameters, you can pass in the
|
46
46
|
# +:include_request+ option, which will pass in the request
|
47
47
|
# object as the second argument when calling the serializer.
|
48
48
|
#
|
49
|
-
# plugin :json, :
|
49
|
+
# plugin :json, include_request: true, serializer: proc{|o, request| ...}
|
50
50
|
#
|
51
51
|
# The default content-type is 'application/json', but you can change that
|
52
52
|
# using the +:content_type+ option:
|
53
53
|
#
|
54
|
-
# plugin :json, :
|
54
|
+
# plugin :json, content_type: 'application/xml'
|
55
55
|
module Json
|
56
56
|
DEFAULT_SERIALIZER = :to_json.to_proc
|
57
57
|
|
58
|
-
OPTS = {}.freeze
|
59
|
-
RodaPlugins.deprecate_constant(self, :OPTS)
|
60
|
-
DEFAULT_CONTENT_TYPE = 'application/json'.freeze
|
61
|
-
RodaPlugins.deprecate_constant(self, :DEFAULT_CONTENT_TYPE)
|
62
|
-
|
63
58
|
# Set the classes to automatically convert to JSON, and the serializer to use.
|
64
|
-
def self.configure(app, opts=
|
59
|
+
def self.configure(app, opts=OPTS)
|
65
60
|
classes = opts[:classes] || [Array, Hash]
|
66
61
|
app.opts[:json_result_classes] ||= []
|
67
62
|
app.opts[:json_result_classes] += classes
|
@@ -70,7 +65,7 @@ class Roda
|
|
70
65
|
|
71
66
|
app.opts[:json_result_serializer] = opts[:serializer] || app.opts[:json_result_serializer] || DEFAULT_SERIALIZER
|
72
67
|
|
73
|
-
app.opts[:json_result_include_request] = opts[:include_request]
|
68
|
+
app.opts[:json_result_include_request] = opts[:include_request] if opts.has_key?(:include_request)
|
74
69
|
|
75
70
|
app.opts[:json_result_content_type] = opts[:content_type] || 'application/json'.freeze
|
76
71
|
end
|
@@ -83,9 +78,6 @@ class Roda
|
|
83
78
|
end
|
84
79
|
|
85
80
|
module RequestMethods
|
86
|
-
CONTENT_TYPE = 'Content-Type'.freeze
|
87
|
-
RodaPlugins.deprecate_constant(self, :CONTENT_TYPE)
|
88
|
-
|
89
81
|
private
|
90
82
|
|
91
83
|
# If the result is an instance of one of the json_result_classes,
|
@@ -14,17 +14,6 @@ class Roda
|
|
14
14
|
DEFAULT_ERROR_HANDLER = proc{|r| r.halt [400, {}, []]}
|
15
15
|
DEFAULT_PARSER = JSON.method(:parse)
|
16
16
|
|
17
|
-
OPTS = {}.freeze
|
18
|
-
RodaPlugins.deprecate_constant(self, :OPTS)
|
19
|
-
JSON_PARAMS_KEY = "roda.json_params".freeze
|
20
|
-
RodaPlugins.deprecate_constant(self, :JSON_PARAMS_KEY)
|
21
|
-
INPUT_KEY = "rack.input".freeze
|
22
|
-
RodaPlugins.deprecate_constant(self, :INPUT_KEY)
|
23
|
-
FORM_HASH_KEY = "rack.request.form_hash".freeze
|
24
|
-
RodaPlugins.deprecate_constant(self, :FORM_HASH_KEY)
|
25
|
-
FORM_INPUT_KEY = "rack.request.form_input".freeze
|
26
|
-
RodaPlugins.deprecate_constant(self, :FORM_INPUT_KEY)
|
27
|
-
|
28
17
|
# Handle options for the json_parser plugin:
|
29
18
|
# :error_handler :: A proc to call if an exception is raised when
|
30
19
|
# parsing a JSON request body. The proc is called
|
@@ -36,10 +25,10 @@ class Roda
|
|
36
25
|
# :include_request :: If true, the parser will be called with the request
|
37
26
|
# object as the second argument, so the parser needs
|
38
27
|
# to respond to +call(str, request)+.
|
39
|
-
def self.configure(app, opts=
|
28
|
+
def self.configure(app, opts=OPTS)
|
40
29
|
app.opts[:json_parser_error_handler] = opts[:error_handler] || app.opts[:json_parser_error_handler] || DEFAULT_ERROR_HANDLER
|
41
30
|
app.opts[:json_parser_parser] = opts[:parser] || app.opts[:json_parser_parser] || DEFAULT_PARSER
|
42
|
-
app.opts[:json_parser_include_request] = opts[:include_request]
|
31
|
+
app.opts[:json_parser_include_request] = opts[:include_request] if opts.has_key?(:include_request)
|
43
32
|
end
|
44
33
|
|
45
34
|
module RequestMethods
|
data/lib/roda/plugins/mailer.rb
CHANGED
@@ -7,14 +7,15 @@ class Roda
|
|
7
7
|
module RodaPlugins
|
8
8
|
# The mailer plugin allows your Roda application to send emails easily.
|
9
9
|
#
|
10
|
-
# class
|
10
|
+
# class Mailer < Roda
|
11
11
|
# plugin :render
|
12
12
|
# plugin :mailer
|
13
13
|
#
|
14
14
|
# route do |r|
|
15
|
-
# r.on "albums" do
|
16
|
-
#
|
17
|
-
#
|
15
|
+
# r.on "albums", Integer do |album_id|
|
16
|
+
# @album = Album[album_id]
|
17
|
+
#
|
18
|
+
# r.mail "added" do
|
18
19
|
# from 'from@example.com'
|
19
20
|
# to 'to@example.com'
|
20
21
|
# cc 'cc@example.com'
|
@@ -29,12 +30,12 @@ class Roda
|
|
29
30
|
#
|
30
31
|
# The default method for sending a mail is +sendmail+:
|
31
32
|
#
|
32
|
-
#
|
33
|
+
# Mailer.sendmail("/albums/1/added")
|
33
34
|
#
|
34
35
|
# If you want to return the <tt>Mail::Message</tt> instance for further modification,
|
35
36
|
# you can just use the +mail+ method:
|
36
37
|
#
|
37
|
-
# mail =
|
38
|
+
# mail = Mailer.mail("/albums/1/added")
|
38
39
|
# mail.from 'from2@example.com'
|
39
40
|
# mail.deliver
|
40
41
|
#
|
@@ -43,12 +44,12 @@ class Roda
|
|
43
44
|
# more details):
|
44
45
|
#
|
45
46
|
# Mail.defaults do
|
46
|
-
# delivery_method :smtp, :
|
47
|
+
# delivery_method :smtp, address: 'smtp.example.com', port: 587
|
47
48
|
# end
|
48
49
|
#
|
49
50
|
# You can support multipart emails using +text_part+ and +html_part+:
|
50
51
|
#
|
51
|
-
# r.mail "added" do
|
52
|
+
# r.mail "added" do
|
52
53
|
# from 'from@example.com'
|
53
54
|
# to 'to@example.com'
|
54
55
|
# subject 'Album Added'
|
@@ -97,11 +98,22 @@ class Roda
|
|
97
98
|
# # ...
|
98
99
|
# end
|
99
100
|
#
|
101
|
+
# You can pass arguments when calling +mail+ or +sendmail+, and they
|
102
|
+
# will be yielded as additional arguments to the appropriate +r.mail+ block:
|
103
|
+
#
|
104
|
+
# Mailer.sendmail('/welcome/1', 'foo@example.com')
|
105
|
+
#
|
106
|
+
# r.mail 'welcome' do |user_id, mail_from|
|
107
|
+
# from mail_from
|
108
|
+
# to User[user_id].email
|
109
|
+
# # ...
|
110
|
+
# end
|
111
|
+
#
|
100
112
|
# By default, the mailer uses text/plain as the Content-Type for emails.
|
101
113
|
# You can override the default by specifying a :content_type option when
|
102
114
|
# loading the plugin:
|
103
115
|
#
|
104
|
-
# plugin :mailer, :
|
116
|
+
# plugin :mailer, content_type: 'text/html'
|
105
117
|
#
|
106
118
|
# The mailer plugin does support being used inside a Roda application
|
107
119
|
# that is handling web requests, where the routing block for mails and
|
@@ -110,43 +122,21 @@ class Roda
|
|
110
122
|
# Roda application if you want your helper methods to automatically be
|
111
123
|
# available in your email views.
|
112
124
|
module Mailer
|
113
|
-
OPTS = {}.freeze
|
114
|
-
RodaPlugins.deprecate_constant(self, :OPTS)
|
115
|
-
REQUEST_METHOD = "REQUEST_METHOD".freeze
|
116
|
-
RodaPlugins.deprecate_constant(self, :REQUEST_METHOD)
|
117
|
-
PATH_INFO = "PATH_INFO".freeze
|
118
|
-
RodaPlugins.deprecate_constant(self, :PATH_INFO)
|
119
|
-
SCRIPT_NAME = 'SCRIPT_NAME'.freeze
|
120
|
-
RodaPlugins.deprecate_constant(self, :SCRIPT_NAME)
|
121
|
-
EMPTY_STRING = ''.freeze
|
122
|
-
RodaPlugins.deprecate_constant(self, :EMPTY_STRING)
|
123
|
-
RACK_INPUT = 'rack.input'.freeze
|
124
|
-
RodaPlugins.deprecate_constant(self, :RACK_INPUT)
|
125
|
-
RODA_MAIL = 'roda.mail'.freeze
|
126
|
-
RodaPlugins.deprecate_constant(self, :RODA_MAIL)
|
127
|
-
RODA_MAIL_ARGS = 'roda.mail_args'.freeze
|
128
|
-
RodaPlugins.deprecate_constant(self, :RODA_MAIL_ARGS)
|
129
|
-
MAIL = "MAIL".freeze
|
130
|
-
RodaPlugins.deprecate_constant(self, :MAIL)
|
131
|
-
CONTENT_TYPE = 'Content-Type'.freeze
|
132
|
-
RodaPlugins.deprecate_constant(self, :CONTENT_TYPE)
|
133
|
-
TEXT_PLAIN = "text/plain".freeze
|
134
|
-
RodaPlugins.deprecate_constant(self, :TEXT_PLAIN)
|
135
|
-
|
136
125
|
# Error raised when the using the mail class method, but the routing
|
137
126
|
# tree doesn't return the mail object.
|
138
127
|
class Error < ::Roda::RodaError; end
|
139
128
|
|
140
129
|
# Set the options for the mailer. Options:
|
141
130
|
# :content_type :: The default content type for emails (default: text/plain)
|
142
|
-
def self.configure(app, opts=
|
143
|
-
app.opts[:mailer] = (app.opts[:mailer]||
|
131
|
+
def self.configure(app, opts=OPTS)
|
132
|
+
app.opts[:mailer] = (app.opts[:mailer]||OPTS).merge(opts).freeze
|
144
133
|
end
|
145
134
|
|
146
135
|
module ClassMethods
|
147
136
|
# Return a Mail::Message instance for the email for the given request path
|
148
|
-
# and arguments.
|
149
|
-
#
|
137
|
+
# and arguments. Any arguments given are yielded to the appropriate +r.mail+
|
138
|
+
# block after any usual match block arguments. You can further manipulate the
|
139
|
+
#returned mail object before calling +deliver+ to send the mail.
|
150
140
|
def mail(path, *args)
|
151
141
|
mail = ::Mail.new
|
152
142
|
catch(:no_mail) do
|
@@ -157,7 +147,7 @@ class Roda
|
|
157
147
|
end
|
158
148
|
end
|
159
149
|
|
160
|
-
# Calls +mail+ and immediately sends the resulting mail.
|
150
|
+
# Calls +mail+ with given arguments and immediately sends the resulting mail.
|
161
151
|
def sendmail(*args)
|
162
152
|
if m = mail(*args)
|
163
153
|
m.deliver
|
@@ -228,7 +218,7 @@ class Roda
|
|
228
218
|
# Add delegates for common email methods.
|
229
219
|
[:from, :to, :cc, :bcc, :subject].each do |meth|
|
230
220
|
define_method(meth) do |*args|
|
231
|
-
env['roda.mail'].
|
221
|
+
env['roda.mail'].public_send(meth, *args)
|
232
222
|
nil
|
233
223
|
end
|
234
224
|
end
|
@@ -267,7 +257,7 @@ class Roda
|
|
267
257
|
# Set the text_part or html_part (depending on the method) in the related email,
|
268
258
|
# using the given body and optional headers.
|
269
259
|
def _mail_part(meth, body, headers=nil)
|
270
|
-
env['roda.mail'].
|
260
|
+
env['roda.mail'].public_send(meth) do
|
271
261
|
body(body)
|
272
262
|
headers(headers) if headers
|
273
263
|
end
|