roda 2.29.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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