roda 2.29.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|