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.
Files changed (170) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +52 -0
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +51 -109
  5. data/Rakefile +7 -14
  6. data/doc/conventions.rdoc +4 -4
  7. data/doc/release_notes/1.2.0.txt +1 -1
  8. data/doc/release_notes/3.0.0.txt +84 -0
  9. data/lib/roda.rb +25 -79
  10. data/lib/roda/plugins/assets.rb +25 -58
  11. data/lib/roda/plugins/assets_preloading.rb +0 -5
  12. data/lib/roda/plugins/backtracking_array.rb +0 -5
  13. data/lib/roda/plugins/branch_locals.rb +3 -3
  14. data/lib/roda/plugins/caching.rb +5 -38
  15. data/lib/roda/plugins/chunked.rb +7 -25
  16. data/lib/roda/plugins/class_level_routing.rb +2 -2
  17. data/lib/roda/plugins/content_for.rb +7 -10
  18. data/lib/roda/plugins/cookies.rb +3 -3
  19. data/lib/roda/plugins/csrf.rb +2 -2
  20. data/lib/roda/plugins/delegate.rb +3 -3
  21. data/lib/roda/plugins/drop_body.rb +0 -7
  22. data/lib/roda/plugins/empty_root.rb +0 -3
  23. data/lib/roda/plugins/error_email.rb +4 -6
  24. data/lib/roda/plugins/error_handler.rb +1 -2
  25. data/lib/roda/plugins/error_mail.rb +3 -6
  26. data/lib/roda/plugins/flash.rb +0 -4
  27. data/lib/roda/plugins/h.rb +5 -0
  28. data/lib/roda/plugins/hash_matcher.rb +4 -2
  29. data/lib/roda/plugins/head.rb +5 -7
  30. data/lib/roda/plugins/header_matchers.rb +12 -33
  31. data/lib/roda/plugins/heartbeat.rb +2 -7
  32. data/lib/roda/plugins/indifferent_params.rb +2 -2
  33. data/lib/roda/plugins/json.rb +6 -14
  34. data/lib/roda/plugins/json_parser.rb +2 -13
  35. data/lib/roda/plugins/mailer.rb +29 -39
  36. data/lib/roda/plugins/match_affix.rb +0 -5
  37. data/lib/roda/plugins/middleware.rb +10 -15
  38. data/lib/roda/plugins/multi_route.rb +8 -5
  39. data/lib/roda/plugins/multi_run.rb +1 -0
  40. data/lib/roda/plugins/named_templates.rb +2 -2
  41. data/lib/roda/plugins/optimized_string_matchers.rb +0 -3
  42. data/lib/roda/plugins/padrino_render.rb +6 -9
  43. data/lib/roda/plugins/param_matchers.rb +6 -6
  44. data/lib/roda/plugins/params_capturing.rb +15 -35
  45. data/lib/roda/plugins/partials.rb +3 -8
  46. data/lib/roda/plugins/path.rb +5 -5
  47. data/lib/roda/plugins/path_matchers.rb +3 -3
  48. data/lib/roda/plugins/path_rewriter.rb +4 -9
  49. data/lib/roda/plugins/placeholder_string_matchers.rb +1 -1
  50. data/lib/roda/plugins/precompile_templates.rb +10 -20
  51. data/lib/roda/plugins/public.rb +6 -9
  52. data/lib/roda/plugins/render.rb +50 -171
  53. data/lib/roda/plugins/render_each.rb +4 -7
  54. data/lib/roda/plugins/render_locals.rb +6 -20
  55. data/lib/roda/plugins/request_headers.rb +2 -4
  56. data/lib/roda/plugins/run_append_slash.rb +1 -4
  57. data/lib/roda/plugins/run_handler.rb +4 -7
  58. data/lib/roda/plugins/shared_vars.rb +3 -6
  59. data/lib/roda/plugins/sinatra_helpers.rb +11 -40
  60. data/lib/roda/plugins/slash_path_empty.rb +0 -3
  61. data/lib/roda/plugins/static.rb +2 -2
  62. data/lib/roda/plugins/static_routing.rb +2 -3
  63. data/lib/roda/plugins/streaming.rb +15 -108
  64. data/lib/roda/plugins/strip_path_prefix.rb +1 -1
  65. data/lib/roda/plugins/symbol_matchers.rb +7 -23
  66. data/lib/roda/plugins/type_routing.rb +4 -9
  67. data/lib/roda/plugins/view_options.rb +10 -66
  68. data/lib/roda/version.rb +2 -2
  69. data/spec/all.rb +0 -2
  70. data/spec/composition_spec.rb +1 -1
  71. data/spec/env_spec.rb +1 -1
  72. data/spec/freeze_spec.rb +1 -1
  73. data/spec/integration_spec.rb +1 -1
  74. data/spec/matchers_spec.rb +26 -70
  75. data/spec/opts_spec.rb +1 -1
  76. data/spec/plugin/all_verbs_spec.rb +1 -1
  77. data/spec/plugin/assets_preloading_spec.rb +1 -1
  78. data/spec/plugin/assets_spec.rb +43 -27
  79. data/spec/plugin/backtracking_array_spec.rb +1 -1
  80. data/spec/plugin/branch_locals_spec.rb +1 -1
  81. data/spec/plugin/caching_spec.rb +1 -1
  82. data/spec/plugin/chunked_spec.rb +1 -1
  83. data/spec/plugin/class_level_routing_spec.rb +1 -1
  84. data/spec/plugin/class_matchers_spec.rb +1 -1
  85. data/spec/plugin/content_for_spec.rb +2 -7
  86. data/spec/plugin/cookies_spec.rb +1 -1
  87. data/spec/plugin/csrf_spec.rb +1 -1
  88. data/spec/plugin/default_headers_spec.rb +1 -1
  89. data/spec/plugin/default_status_spec.rb +1 -1
  90. data/spec/plugin/delay_build_spec.rb +1 -1
  91. data/spec/plugin/delegate_spec.rb +1 -1
  92. data/spec/plugin/delete_empty_headers_spec.rb +1 -1
  93. data/spec/plugin/disallow_file_uploads_spec.rb +2 -2
  94. data/spec/plugin/drop_body_spec.rb +1 -1
  95. data/spec/plugin/empty_root_spec.rb +1 -1
  96. data/spec/plugin/environments_spec.rb +1 -1
  97. data/spec/plugin/error_email_spec.rb +1 -1
  98. data/spec/plugin/error_handler_spec.rb +1 -1
  99. data/spec/plugin/error_mail_spec.rb +2 -2
  100. data/spec/plugin/flash_spec.rb +1 -1
  101. data/spec/plugin/h_spec.rb +1 -1
  102. data/spec/plugin/halt_spec.rb +2 -2
  103. data/spec/plugin/hash_matcher_spec.rb +1 -1
  104. data/spec/plugin/head_spec.rb +1 -1
  105. data/spec/plugin/header_matchers_spec.rb +4 -47
  106. data/spec/plugin/heartbeat_spec.rb +1 -1
  107. data/spec/plugin/hooks_spec.rb +1 -1
  108. data/spec/plugin/indifferent_params_spec.rb +1 -1
  109. data/spec/plugin/json_parser_spec.rb +12 -1
  110. data/spec/plugin/json_spec.rb +8 -1
  111. data/spec/plugin/mailer_spec.rb +1 -1
  112. data/spec/plugin/match_affix_spec.rb +1 -1
  113. data/spec/plugin/middleware_spec.rb +15 -1
  114. data/spec/plugin/module_include_spec.rb +1 -1
  115. data/spec/plugin/multi_route_spec.rb +5 -3
  116. data/spec/plugin/multi_run_spec.rb +1 -1
  117. data/spec/plugin/multi_view_spec.rb +1 -1
  118. data/spec/plugin/named_templates_spec.rb +1 -1
  119. data/spec/plugin/not_allowed_spec.rb +1 -1
  120. data/spec/plugin/not_found_spec.rb +1 -1
  121. data/spec/plugin/optimized_string_matchers_spec.rb +1 -1
  122. data/spec/plugin/padrino_render_spec.rb +1 -1
  123. data/spec/plugin/param_matchers_spec.rb +1 -1
  124. data/spec/plugin/params_capturing_spec.rb +6 -22
  125. data/spec/plugin/partials_spec.rb +1 -1
  126. data/spec/plugin/pass_spec.rb +1 -1
  127. data/spec/plugin/path_matchers_spec.rb +1 -1
  128. data/spec/plugin/path_rewriter_spec.rb +1 -1
  129. data/spec/plugin/path_spec.rb +1 -1
  130. data/spec/plugin/placeholder_string_matchers_spec.rb +3 -36
  131. data/spec/plugin/precompile_templates_spec.rb +1 -17
  132. data/spec/plugin/public_spec.rb +3 -4
  133. data/spec/plugin/render_each_spec.rb +1 -1
  134. data/spec/plugin/render_locals_spec.rb +1 -1
  135. data/spec/plugin/render_spec.rb +28 -114
  136. data/spec/plugin/request_headers_spec.rb +1 -1
  137. data/spec/plugin/response_request_spec.rb +1 -1
  138. data/spec/plugin/run_append_slash_spec.rb +1 -1
  139. data/spec/plugin/run_handler_spec.rb +1 -1
  140. data/spec/plugin/shared_vars_spec.rb +1 -1
  141. data/spec/plugin/sinatra_helpers_spec.rb +1 -1
  142. data/spec/plugin/slash_path_empty_spec.rb +1 -1
  143. data/spec/plugin/static_routing_spec.rb +1 -1
  144. data/spec/plugin/static_spec.rb +1 -1
  145. data/spec/plugin/status_303_spec.rb +1 -1
  146. data/spec/plugin/status_handler_spec.rb +1 -1
  147. data/spec/plugin/streaming_spec.rb +1 -106
  148. data/spec/plugin/strip_path_prefix_spec.rb +1 -1
  149. data/spec/plugin/symbol_matchers_spec.rb +1 -77
  150. data/spec/plugin/symbol_status_spec.rb +1 -1
  151. data/spec/plugin/symbol_views_spec.rb +1 -1
  152. data/spec/plugin/type_routing_spec.rb +1 -1
  153. data/spec/plugin/unescape_path_spec.rb +1 -1
  154. data/spec/plugin/view_options_spec.rb +16 -110
  155. data/spec/plugin_spec.rb +1 -1
  156. data/spec/redirect_spec.rb +1 -1
  157. data/spec/request_spec.rb +1 -1
  158. data/spec/response_spec.rb +1 -1
  159. data/spec/session_spec.rb +1 -1
  160. data/spec/spec_helper.rb +1 -3
  161. data/spec/version_spec.rb +1 -1
  162. metadata +6 -26
  163. data/lib/roda/plugins/_erubis_escaping.rb +0 -59
  164. data/lib/roda/plugins/per_thread_caching.rb +0 -71
  165. data/lib/roda/plugins/static_path_info.rb +0 -12
  166. data/lib/roda/plugins/view_subdirs.rb +0 -7
  167. data/lib/roda/plugins/websockets.rb +0 -107
  168. data/spec/plugin/_erubis_escaping_spec.rb +0 -97
  169. data/spec/plugin/per_thread_caching_spec.rb +0 -28
  170. data/spec/plugin/websockets_spec.rb +0 -84
@@ -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 :foo=>'bar' do
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
- self::RodaRequest.send(:define_method, :"match_#{key}", &block)
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
@@ -18,7 +18,7 @@ class Roda
18
18
  # 'a'
19
19
  # end
20
20
  #
21
- # r.is 'b', :method=>[:get, :post] do
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. Search engines and other bots may send a
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 engine's from crawling your website.
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] = RodaPlugins::EMPTY_ARRAY
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 :header=>'HTTP-X-App-Token' do |header_value|
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 :host=>'foo.example.com' do
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
- # By default the +:host+ matcher does not yield matchers, but if you use a regexp
34
- # and set the +:host_matcher_captures+ option for the application, it will
35
- # yield regexp captures:
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 :user_agent=>/Chrome\/([.\d]+)/ do |chrome_version|
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 :accept=>'text/csv' do
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
- key = key.upcase.tr("-","_")
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) && roda_class.opts[:host_matcher_captures]
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, :path=>'/status'
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=RodaPlugins::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
 
@@ -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, :classes=>[Array, Hash, Sequel::Model]
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, :serializer=>proc{|o| o.to_json(root: true)}
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, :include_request=>true, :serializer=>proc{|o, request| ...}
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, :content_type=>'application/xml'
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=RodaPlugins::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] || app.opts[:json_result_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=RodaPlugins::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] || app.opts[:json_parser_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
@@ -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 App < Roda
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
- # r.mail "added" do |album|
17
- # @album = album
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
- # App.sendmail("/albums/added", Album[1])
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 = App.mail("/albums/added", Album[1])
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, :address=>'smtp.example.com', :port=>587
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 |album_added|
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, :content_type=>'text/html'
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=RodaPlugins::OPTS)
143
- app.opts[:mailer] = (app.opts[:mailer]||RodaPlugins::OPTS).merge(opts).freeze
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. You can further manipulate the returned mail object before
149
- # calling +deliver+ to send the mail.
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'].send(meth, *args)
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'].send(meth) do
260
+ env['roda.mail'].public_send(meth) do
271
261
  body(body)
272
262
  headers(headers) if headers
273
263
  end