hanami 2.1.0.beta2.1 → 2.1.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +30 -0
  3. data/hanami.gemspec +3 -3
  4. data/lib/hanami/config/actions.rb +16 -3
  5. data/lib/hanami/config/assets.rb +1 -1
  6. data/lib/hanami/config/views.rb +10 -2
  7. data/lib/hanami/config.rb +21 -12
  8. data/lib/hanami/extensions/action/slice_configured_action.rb +5 -5
  9. data/lib/hanami/extensions/action.rb +4 -4
  10. data/lib/hanami/extensions/view/context.rb +111 -19
  11. data/lib/hanami/extensions/view/part.rb +64 -3
  12. data/lib/hanami/extensions/view/scope.rb +7 -0
  13. data/lib/hanami/extensions/view/slice_configured_context.rb +12 -8
  14. data/lib/hanami/extensions/view/slice_configured_helpers.rb +12 -1
  15. data/lib/hanami/extensions/view/slice_configured_part.rb +71 -0
  16. data/lib/hanami/extensions/view/slice_configured_view.rb +14 -6
  17. data/lib/hanami/extensions/view/standard_helpers.rb +4 -0
  18. data/lib/hanami/extensions/view.rb +5 -3
  19. data/lib/hanami/helpers/assets_helper.rb +47 -79
  20. data/lib/hanami/routes.rb +33 -2
  21. data/lib/hanami/slice.rb +12 -2
  22. data/lib/hanami/slice_registrar.rb +48 -23
  23. data/lib/hanami/version.rb +1 -1
  24. data/lib/hanami/web/rack_logger.rb +70 -2
  25. data/lib/hanami/web/welcome.html.erb +203 -0
  26. data/lib/hanami/web/welcome.rb +46 -0
  27. data/spec/integration/assets/assets_spec.rb +14 -3
  28. data/spec/integration/logging/request_logging_spec.rb +65 -7
  29. data/spec/integration/rack_app/method_override_spec.rb +97 -0
  30. data/spec/integration/slices_spec.rb +275 -5
  31. data/spec/integration/view/context/assets_spec.rb +0 -8
  32. data/spec/integration/view/context/inflector_spec.rb +0 -8
  33. data/spec/integration/view/context/settings_spec.rb +0 -8
  34. data/spec/integration/view/helpers/part_helpers_spec.rb +2 -2
  35. data/spec/integration/view/helpers/user_defined_helpers/part_helpers_spec.rb +10 -10
  36. data/spec/integration/view/parts/default_rendering_spec.rb +138 -0
  37. data/spec/integration/web/welcome_view_spec.rb +84 -0
  38. data/spec/support/app_integration.rb +22 -4
  39. data/spec/unit/hanami/config/render_detailed_errors_spec.rb +1 -1
  40. data/spec/unit/hanami/helpers/assets_helper/{audio_spec.rb → audio_tag_spec.rb} +10 -14
  41. data/spec/unit/hanami/helpers/assets_helper/{favicon_spec.rb → favicon_tag_spec.rb} +7 -11
  42. data/spec/unit/hanami/helpers/assets_helper/{image_spec.rb → image_tag_spec.rb} +8 -12
  43. data/spec/unit/hanami/helpers/assets_helper/{javascript_spec.rb → javascript_tag_spec.rb} +14 -18
  44. data/spec/unit/hanami/helpers/assets_helper/{stylesheet_spec.rb → stylesheet_tag_spec.rb} +12 -16
  45. data/spec/unit/hanami/helpers/assets_helper/{video_spec.rb → video_tag_spec.rb} +11 -11
  46. data/spec/unit/hanami/version_spec.rb +1 -1
  47. metadata +28 -19
@@ -3,19 +3,30 @@
3
3
  module Hanami
4
4
  module Extensions
5
5
  module View
6
- # @api private
6
+ # Provides slice-specific helper methods any view object requiring access to helpers.
7
+ #
8
+ # @api public
9
+ # @since 2.1.0
7
10
  class SliceConfiguredHelpers < Module
8
11
  attr_reader :slice
9
12
 
13
+ # @api private
14
+ # @since 2.1.0
10
15
  def initialize(slice)
11
16
  super()
12
17
  @slice = slice
13
18
  end
14
19
 
20
+ # @api private
21
+ # @since 2.1.0
15
22
  def extended(klass)
16
23
  include_helpers(klass)
17
24
  end
18
25
 
26
+ # @return [String]
27
+ #
28
+ # @api public
29
+ # @since 2.1.0
19
30
  def inspect
20
31
  "#<#{self.class.name}[#{slice.name}]>"
21
32
  end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hanami
4
+ module Extensions
5
+ module View
6
+ # Provides slice-specific configuration and behavior for any view part class defined within a
7
+ # slice's module namespace.
8
+ #
9
+ # @api public
10
+ # @since 2.1.0
11
+ class SliceConfiguredPart < Module
12
+ attr_reader :slice
13
+
14
+ # @api private
15
+ # @since 2.1.0
16
+ def initialize(slice)
17
+ super()
18
+ @slice = slice
19
+ end
20
+
21
+ # @api private
22
+ # @since 2.1.0
23
+ def extended(klass)
24
+ define_new
25
+ end
26
+
27
+ # @return [String]
28
+ #
29
+ # @api public
30
+ # @since 2.1.0
31
+ def inspect
32
+ "#<#{self.class.name}[#{slice.name}]>"
33
+ end
34
+
35
+ private
36
+
37
+ # Defines a `.new` method on the part class that provides a default `rendering:` argument of
38
+ # a rendering coming from a view configured for the slice. This means that any part can be
39
+ # initialized standalone (with a `value:` only) and still have access to all the integrated
40
+ # view facilities from the slice, such as helpers. This is helpful when unit testing parts.
41
+ #
42
+ # @example
43
+ # module MyApp::Views::Parts
44
+ # class Post < MyApp::View::Part
45
+ # def title_tag
46
+ # helpers.h1(value.title)
47
+ # end
48
+ # end
49
+ # end
50
+ #
51
+ # # Useful when unit testing parts
52
+ # part = MyApp::Views::Parts::Post.new(value: hello_world_post)
53
+ # part.title_tag # => "<h1>Hello world</h1>"
54
+ def define_new
55
+ slice = self.slice
56
+
57
+ define_method(:new) do |**args|
58
+ return super(**args) if args.key?(:rendering)
59
+
60
+ slice_rendering = Class.new(Hanami::View)
61
+ .configure_for_slice(slice)
62
+ .new
63
+ .rendering
64
+
65
+ super(rendering: slice_rendering, **args)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -3,11 +3,11 @@
3
3
  module Hanami
4
4
  module Extensions
5
5
  module View
6
- # Provides slice-specific configuration and behavior for any view class defined
7
- # within a slice's module namespace.
6
+ # Provides slice-specific configuration and behavior for any view class defined within a
7
+ # slice's module namespace.
8
8
  #
9
- # @api private
10
- # @since 2.0.0
9
+ # @api public
10
+ # @since 2.1.0
11
11
  class SliceConfiguredView < Module
12
12
  TEMPLATES_DIR = "templates"
13
13
  VIEWS_DIR = "views"
@@ -16,17 +16,25 @@ module Hanami
16
16
 
17
17
  attr_reader :slice
18
18
 
19
+ # @api private
20
+ # @since 2.1.0
19
21
  def initialize(slice)
20
22
  super()
21
23
  @slice = slice
22
24
  end
23
25
 
26
+ # @api private
27
+ # @since 2.1.0
24
28
  def extended(view_class)
25
29
  load_app_view
26
30
  configure_view(view_class)
27
31
  define_inherited
28
32
  end
29
33
 
34
+ # @return [String]
35
+ #
36
+ # @api public
37
+ # @since 2.1.0
30
38
  def inspect
31
39
  "#<#{self.class.name}[#{slice.name}]>"
32
40
  end
@@ -108,7 +116,7 @@ module Hanami
108
116
  # - We are a slice, and the view's inherited `paths` is identical to the parent's config
109
117
  # (which would result in the view in a slice erroneously trying to find templates in
110
118
  # the app)
111
- if (!slice.parent && view_class.config.paths.empty?) ||
119
+ if view_class.config.paths.empty? ||
112
120
  (slice.parent && view_class.config.paths.map(&:dir) == [templates_path(slice.parent)])
113
121
  view_class.config.paths = templates_path(slice)
114
122
  end
@@ -178,7 +186,7 @@ module Hanami
178
186
  else
179
187
  views_namespace.const_set(:Part, Class.new(part_superclass).tap { |klass|
180
188
  # Give the slice to `configure_for_slice`, since it cannot be inferred when it is
181
- # called via `.inherited`, since the class is anonymous at this point
189
+ # called via `.inherited`, because the class is anonymous at this point
182
190
  klass.configure_for_slice(slice)
183
191
  })
184
192
  end
@@ -3,6 +3,10 @@
3
3
  module Hanami
4
4
  module Extensions
5
5
  module View
6
+ # Module including the standard library of Hanami helpers
7
+ #
8
+ # @api public
9
+ # @since 2.1.0
6
10
  module StandardHelpers
7
11
  include Hanami::View::Helpers::EscapeHelper
8
12
  include Hanami::View::Helpers::NumberFormattingHelper
@@ -7,13 +7,13 @@ module Hanami
7
7
  module Extensions
8
8
  # Integrated behavior for `Hanami::View` classes within Hanami apps.
9
9
  #
10
- # This is NOT RELEASED as of 2.0.0.
11
- #
12
10
  # @see Hanami::View
13
11
  #
14
- # @api private
12
+ # @api public
13
+ # @since 2.1.0
15
14
  module View
16
15
  # @api private
16
+ # @since 2.1.0
17
17
  def self.included(view_class)
18
18
  super
19
19
 
@@ -22,8 +22,10 @@ module Hanami
22
22
  end
23
23
 
24
24
  # @api private
25
+ # @since 2.1.0
25
26
  module ClassMethods
26
27
  # @api private
28
+ # @since 2.1.0
27
29
  def configure_for_slice(slice)
28
30
  extend SliceConfiguredView.new(slice)
29
31
  end
@@ -99,62 +99,62 @@ module Hanami
99
99
  #
100
100
  # @example Single Asset
101
101
  #
102
- # <%= js "application" %>
102
+ # <%= javascript_tag "application" %>
103
103
  #
104
104
  # # <script src="/assets/application.js" type="text/javascript"></script>
105
105
  #
106
106
  # @example Multiple Assets
107
107
  #
108
- # <%= js "application", "dashboard" %>
108
+ # <%= javascript_tag "application", "dashboard" %>
109
109
  #
110
110
  # # <script src="/assets/application.js" type="text/javascript"></script>
111
111
  # # <script src="/assets/dashboard.js" type="text/javascript"></script>
112
112
  #
113
113
  # @example Asynchronous Execution
114
114
  #
115
- # <%= js "application", async: true %>
115
+ # <%= javascript_tag "application", async: true %>
116
116
  #
117
117
  # # <script src="/assets/application.js" type="text/javascript" async="async"></script>
118
118
  #
119
119
  # @example Subresource Integrity
120
120
  #
121
- # <%= js "application" %>
121
+ # <%= javascript_tag "application" %>
122
122
  #
123
123
  # # <script src="/assets/application-28a6b886de2372ee3922fcaf3f78f2d8.js"
124
124
  # # type="text/javascript" integrity="sha384-oqVu...Y8wC" crossorigin="anonymous"></script>
125
125
  #
126
126
  # @example Subresource Integrity for 3rd Party Scripts
127
127
  #
128
- # <%= js "https://example.com/assets/example.js", integrity: "sha384-oqVu...Y8wC" %>
128
+ # <%= javascript_tag "https://example.com/assets/example.js", integrity: "sha384-oqVu...Y8wC" %>
129
129
  #
130
130
  # # <script src="https://example.com/assets/example.js" type="text/javascript"
131
131
  # # integrity="sha384-oqVu...Y8wC" crossorigin="anonymous"></script>
132
132
  #
133
133
  # @example Deferred Execution
134
134
  #
135
- # <%= js "application", defer: true %>
135
+ # <%= javascript_tag "application", defer: true %>
136
136
  #
137
137
  # # <script src="/assets/application.js" type="text/javascript" defer="defer"></script>
138
138
  #
139
139
  # @example Absolute URL
140
140
  #
141
- # <%= js "https://code.jquery.com/jquery-2.1.4.min.js" %>
141
+ # <%= javascript_tag "https://code.jquery.com/jquery-2.1.4.min.js" %>
142
142
  #
143
143
  # # <script src="https://code.jquery.com/jquery-2.1.4.min.js" type="text/javascript"></script>
144
144
  #
145
145
  # @example Fingerprint Mode
146
146
  #
147
- # <%= js "application" %>
147
+ # <%= javascript_tag "application" %>
148
148
  #
149
149
  # # <script src="/assets/application-28a6b886de2372ee3922fcaf3f78f2d8.js" type="text/javascript"></script>
150
150
  #
151
151
  # @example CDN Mode
152
152
  #
153
- # <%= js "application" %>
153
+ # <%= javascript_tag "application" %>
154
154
  #
155
155
  # # <script src="https://assets.bookshelf.org/assets/application-28a6b886de2372ee3922fcaf3f78f2d8.js"
156
156
  # # type="text/javascript"></script>
157
- def javascript(*source_paths, **options)
157
+ def javascript_tag(*source_paths, **options)
158
158
  options = options.reject { |k, _| k.to_sym == :src }
159
159
 
160
160
  _safe_tags(*source_paths) do |source|
@@ -173,14 +173,6 @@ module Hanami
173
173
  end
174
174
  end
175
175
 
176
- # @api public
177
- # @since 2.1.0
178
- alias_method :js, :javascript
179
-
180
- # @api public
181
- # @since 2.1.0
182
- alias_method :javascript_tag, :javascript
183
-
184
176
  # Generate `link` tag for given source(s)
185
177
  #
186
178
  # It accepts one or more strings representing the name of the asset, if it
@@ -211,51 +203,51 @@ module Hanami
211
203
  #
212
204
  # @example Single Asset
213
205
  #
214
- # <%= css "application" %>
206
+ # <%= stylesheet_tag "application" %>
215
207
  #
216
208
  # # <link href="/assets/application.css" type="text/css" rel="stylesheet">
217
209
  #
218
210
  # @example Multiple Assets
219
211
  #
220
- # <%= css "application", "dashboard" %>
212
+ # <%= stylesheet_tag "application", "dashboard" %>
221
213
  #
222
214
  # # <link href="/assets/application.css" type="text/css" rel="stylesheet">
223
215
  # # <link href="/assets/dashboard.css" type="text/css" rel="stylesheet">
224
216
  #
225
217
  # @example Subresource Integrity
226
218
  #
227
- # <%= css "application" %>
219
+ # <%= stylesheet_tag "application" %>
228
220
  #
229
221
  # # <link href="/assets/application-28a6b886de2372ee3922fcaf3f78f2d8.css"
230
222
  # # type="text/css" integrity="sha384-oqVu...Y8wC" crossorigin="anonymous"></script>
231
223
  #
232
224
  # @example Subresource Integrity for 3rd Party Assets
233
225
  #
234
- # <%= css "https://example.com/assets/example.css", integrity: "sha384-oqVu...Y8wC" %>
226
+ # <%= stylesheet_tag "https://example.com/assets/example.css", integrity: "sha384-oqVu...Y8wC" %>
235
227
  #
236
228
  # # <link href="https://example.com/assets/example.css"
237
229
  # # type="text/css" rel="stylesheet" integrity="sha384-oqVu...Y8wC" crossorigin="anonymous"></script>
238
230
  #
239
231
  # @example Absolute URL
240
232
  #
241
- # <%= css "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" %>
233
+ # <%= stylesheet_tag "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" %>
242
234
  #
243
235
  # # <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
244
236
  # # type="text/css" rel="stylesheet">
245
237
  #
246
238
  # @example Fingerprint Mode
247
239
  #
248
- # <%= css "application" %>
240
+ # <%= stylesheet_tag "application" %>
249
241
  #
250
242
  # # <link href="/assets/application-28a6b886de2372ee3922fcaf3f78f2d8.css" type="text/css" rel="stylesheet">
251
243
  #
252
244
  # @example CDN Mode
253
245
  #
254
- # <%= css "application" %>
246
+ # <%= stylesheet_tag "application" %>
255
247
  #
256
248
  # # <link href="https://assets.bookshelf.org/assets/application-28a6b886de2372ee3922fcaf3f78f2d8.css"
257
249
  # # type="text/css" rel="stylesheet">
258
- def stylesheet(*source_paths, **options)
250
+ def stylesheet_tag(*source_paths, **options)
259
251
  options = options.reject { |k, _| k.to_sym == :href }
260
252
 
261
253
  _safe_tags(*source_paths) do |source_path|
@@ -275,14 +267,6 @@ module Hanami
275
267
  end
276
268
  end
277
269
 
278
- # @api public
279
- # @since 2.1.0
280
- alias_method :css, :stylesheet
281
-
282
- # @api public
283
- # @since 2.1.0
284
- alias_method :stylesheet_link_tag, :stylesheet
285
-
286
270
  # Generate `img` tag for given source
287
271
  #
288
272
  # It accepts one string representing the name of the asset, if it comes
@@ -313,40 +297,40 @@ module Hanami
313
297
  #
314
298
  # @example Basic Usage
315
299
  #
316
- # <%= image "logo.png" %>
300
+ # <%= image_tag "logo.png" %>
317
301
  #
318
302
  # # <img src="/assets/logo.png" alt="Logo">
319
303
  #
320
304
  # @example Custom alt Attribute
321
305
  #
322
- # <%= image "logo.png", alt: "Application Logo" %>
306
+ # <%= image_tag "logo.png", alt: "Application Logo" %>
323
307
  #
324
308
  # # <img src="/assets/logo.png" alt="Application Logo">
325
309
  #
326
310
  # @example Custom HTML Attributes
327
311
  #
328
- # <%= image "logo.png", id: "logo", class: "image" %>
312
+ # <%= image_tag "logo.png", id: "logo", class: "image" %>
329
313
  #
330
314
  # # <img src="/assets/logo.png" alt="Logo" id="logo" class="image">
331
315
  #
332
316
  # @example Absolute URL
333
317
  #
334
- # <%= image "https://example-cdn.com/images/logo.png" %>
318
+ # <%= image_tag "https://example-cdn.com/images/logo.png" %>
335
319
  #
336
320
  # # <img src="https://example-cdn.com/images/logo.png" alt="Logo">
337
321
  #
338
322
  # @example Fingerprint Mode
339
323
  #
340
- # <%= image "logo.png" %>
324
+ # <%= image_tag "logo.png" %>
341
325
  #
342
326
  # # <img src="/assets/logo-28a6b886de2372ee3922fcaf3f78f2d8.png" alt="Logo">
343
327
  #
344
328
  # @example CDN Mode
345
329
  #
346
- # <%= image "logo.png" %>
330
+ # <%= image_tag "logo.png" %>
347
331
  #
348
332
  # # <img src="https://assets.bookshelf.org/assets/logo-28a6b886de2372ee3922fcaf3f78f2d8.png" alt="Logo">
349
- def image(source, options = {})
333
+ def image_tag(source, options = {})
350
334
  options = options.reject { |k, _| k.to_sym == :src }
351
335
  attributes = {
352
336
  src: asset_url(source),
@@ -357,10 +341,6 @@ module Hanami
357
341
  tag.img(**attributes)
358
342
  end
359
343
 
360
- # @api public
361
- # @since 2.1.0
362
- alias_method :image_tag, :image
363
-
364
344
  # Generate `link` tag application favicon.
365
345
  #
366
346
  # If no argument is given, it assumes `favico.ico` from the application.
@@ -388,35 +368,35 @@ module Hanami
388
368
  #
389
369
  # @example Basic Usage
390
370
  #
391
- # <%= favicon %>
371
+ # <%= favicon_tag %>
392
372
  #
393
373
  # # <link href="/assets/favicon.ico" rel="shortcut icon" type="image/x-icon">
394
374
  #
395
375
  # @example Custom Path
396
376
  #
397
- # <%= favicon "fav.ico" %>
377
+ # <%= favicon_tag "fav.ico" %>
398
378
  #
399
379
  # # <link href="/assets/fav.ico" rel="shortcut icon" type="image/x-icon">
400
380
  #
401
381
  # @example Custom HTML Attributes
402
382
  #
403
- # <%= favicon "favicon.ico", id: "fav" %>
383
+ # <%= favicon_tag "favicon.ico", id: "fav" %>
404
384
  #
405
385
  # # <link id: "fav" href="/assets/favicon.ico" rel="shortcut icon" type="image/x-icon">
406
386
  #
407
387
  # @example Fingerprint Mode
408
388
  #
409
- # <%= favicon %>
389
+ # <%= favicon_tag %>
410
390
  #
411
391
  # # <link href="/assets/favicon-28a6b886de2372ee3922fcaf3f78f2d8.ico" rel="shortcut icon" type="image/x-icon">
412
392
  #
413
393
  # @example CDN Mode
414
394
  #
415
- # <%= favicon %>
395
+ # <%= favicon_tag %>
416
396
  #
417
397
  # # <link href="https://assets.bookshelf.org/assets/favicon-28a6b886de2372ee3922fcaf3f78f2d8.ico"
418
398
  # rel="shortcut icon" type="image/x-icon">
419
- def favicon(source = DEFAULT_FAVICON, options = {})
399
+ def favicon_tag(source = DEFAULT_FAVICON, options = {})
420
400
  options = options.reject { |k, _| k.to_sym == :href }
421
401
 
422
402
  attributes = {
@@ -429,10 +409,6 @@ module Hanami
429
409
  tag.link(**attributes)
430
410
  end
431
411
 
432
- # @api public
433
- # @since 2.1.0
434
- alias_method :favicon_link_tag, :favicon
435
-
436
412
  # Generate `video` tag for given source
437
413
  #
438
414
  # It accepts one string representing the name of the asset, if it comes
@@ -466,19 +442,19 @@ module Hanami
466
442
  #
467
443
  # @example Basic Usage
468
444
  #
469
- # <%= video "movie.mp4" %>
445
+ # <%= video_tag "movie.mp4" %>
470
446
  #
471
447
  # # <video src="/assets/movie.mp4"></video>
472
448
  #
473
449
  # @example Absolute URL
474
450
  #
475
- # <%= video "https://example-cdn.com/assets/movie.mp4" %>
451
+ # <%= video_tag "https://example-cdn.com/assets/movie.mp4" %>
476
452
  #
477
453
  # # <video src="https://example-cdn.com/assets/movie.mp4"></video>
478
454
  #
479
455
  # @example Custom HTML Attributes
480
456
  #
481
- # <%= video("movie.mp4", autoplay: true, controls: true) %>
457
+ # <%= video_tag("movie.mp4", autoplay: true, controls: true) %>
482
458
  #
483
459
  # # <video src="/assets/movie.mp4" autoplay="autoplay" controls="controls"></video>
484
460
  #
@@ -509,36 +485,32 @@ module Hanami
509
485
  #
510
486
  # @example Without Any Argument
511
487
  #
512
- # <%= video %>
488
+ # <%= video_tag %>
513
489
  #
514
490
  # # ArgumentError
515
491
  #
516
492
  # @example Without src And Without Block
517
493
  #
518
- # <%= video(content: true) %>
494
+ # <%= video_tag(content: true) %>
519
495
  #
520
496
  # # ArgumentError
521
497
  #
522
498
  # @example Fingerprint Mode
523
499
  #
524
- # <%= video "movie.mp4" %>
500
+ # <%= video_tag "movie.mp4" %>
525
501
  #
526
502
  # # <video src="/assets/movie-28a6b886de2372ee3922fcaf3f78f2d8.mp4"></video>
527
503
  #
528
504
  # @example CDN Mode
529
505
  #
530
- # <%= video "movie.mp4" %>
506
+ # <%= video_tag "movie.mp4" %>
531
507
  #
532
508
  # # <video src="https://assets.bookshelf.org/assets/movie-28a6b886de2372ee3922fcaf3f78f2d8.mp4"></video>
533
- def video(source = nil, options = {}, &blk)
509
+ def video_tag(source = nil, options = {}, &blk)
534
510
  options = _source_options(source, options, &blk)
535
511
  tag.video(**options, &blk)
536
512
  end
537
513
 
538
- # @api public
539
- # @since 2.1.0
540
- alias_method :video_tag, :video
541
-
542
514
  # Generate `audio` tag for given source
543
515
  #
544
516
  # It accepts one string representing the name of the asset, if it comes
@@ -572,19 +544,19 @@ module Hanami
572
544
  #
573
545
  # @example Basic Usage
574
546
  #
575
- # <%= audio "song.ogg" %>
547
+ # <%= audio_tag "song.ogg" %>
576
548
  #
577
549
  # # <audio src="/assets/song.ogg"></audio>
578
550
  #
579
551
  # @example Absolute URL
580
552
  #
581
- # <%= audio "https://example-cdn.com/assets/song.ogg" %>
553
+ # <%= audio_tag "https://example-cdn.com/assets/song.ogg" %>
582
554
  #
583
555
  # # <audio src="https://example-cdn.com/assets/song.ogg"></audio>
584
556
  #
585
557
  # @example Custom HTML Attributes
586
558
  #
587
- # <%= audio("song.ogg", autoplay: true, controls: true) %>
559
+ # <%= audio_tag("song.ogg", autoplay: true, controls: true) %>
588
560
  #
589
561
  # # <audio src="/assets/song.ogg" autoplay="autoplay" controls="controls"></audio>
590
562
  #
@@ -615,36 +587,32 @@ module Hanami
615
587
  #
616
588
  # @example Without Any Argument
617
589
  #
618
- # <%= audio %>
590
+ # <%= audio_tag %>
619
591
  #
620
592
  # # ArgumentError
621
593
  #
622
594
  # @example Without src And Without Block
623
595
  #
624
- # <%= audio(controls: true) %>
596
+ # <%= audio_tag(controls: true) %>
625
597
  #
626
598
  # # ArgumentError
627
599
  #
628
600
  # @example Fingerprint Mode
629
601
  #
630
- # <%= audio "song.ogg" %>
602
+ # <%= audio_tag "song.ogg" %>
631
603
  #
632
604
  # # <audio src="/assets/song-28a6b886de2372ee3922fcaf3f78f2d8.ogg"></audio>
633
605
  #
634
606
  # @example CDN Mode
635
607
  #
636
- # <%= audio "song.ogg" %>
608
+ # <%= audio_tag "song.ogg" %>
637
609
  #
638
610
  # # <audio src="https://assets.bookshelf.org/assets/song-28a6b886de2372ee3922fcaf3f78f2d8.ogg"></audio>
639
- def audio(source = nil, options = {}, &blk)
611
+ def audio_tag(source = nil, options = {}, &blk)
640
612
  options = _source_options(source, options, &blk)
641
613
  tag.audio(**options, &blk)
642
614
  end
643
615
 
644
- # @api public
645
- # @since 2.1.0
646
- alias_method :audio_tag, :audio
647
-
648
616
  # It generates the relative or absolute URL for the given asset.
649
617
  # It automatically decides if it has to use the relative or absolute
650
618
  # depending on the configuration and current environment.
data/lib/hanami/routes.rb CHANGED
@@ -60,6 +60,35 @@ module Hanami
60
60
  end
61
61
  end
62
62
 
63
+ # Wrapper class for the (otherwise opaque) proc returned from {.routes}, adding an `#empty?`
64
+ # method that returns true if no routes were defined.
65
+ #
66
+ # This is useful when needing to determine behaviour based on the presence of user-defined
67
+ # routes, such as determining whether to show the Hanami welcome page in {Slice#load_router}.
68
+ #
69
+ # @api private
70
+ # @since 2.1.0
71
+ class RoutesProc < DelegateClass(Proc)
72
+ # @api private
73
+ # @since 2.1.0
74
+ def self.empty
75
+ new(proc {}, empty: true)
76
+ end
77
+
78
+ # @api private
79
+ # @since 2.1.0
80
+ def initialize(proc, empty: false)
81
+ @empty = empty
82
+ super(proc)
83
+ end
84
+
85
+ # @api private
86
+ # @since 2.1.0
87
+ def empty?
88
+ !!@empty
89
+ end
90
+ end
91
+
63
92
  # @api private
64
93
  def self.routes
65
94
  @routes ||= build_routes
@@ -68,9 +97,9 @@ module Hanami
68
97
  class << self
69
98
  # @api private
70
99
  def build_routes(definitions = self.definitions)
71
- return if definitions.empty?
100
+ return RoutesProc.empty if definitions.empty?
72
101
 
73
- proc do
102
+ routes_proc = proc do
74
103
  definitions.each do |(name, args, kwargs, block)|
75
104
  if block
76
105
  public_send(name, *args, **kwargs, &block)
@@ -79,6 +108,8 @@ module Hanami
79
108
  end
80
109
  end
81
110
  end
111
+
112
+ RoutesProc.new(routes_proc)
82
113
  end
83
114
 
84
115
  # @api private