magic-presenter 0.3.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 17e4d44c0c2d9a9e09e7e099a4067b9e6aafe27e1b389cf01808ed0a77d0b9ae
4
- data.tar.gz: 7d492486c2f4edb2407af461794e1f0c7e53c7f6b93e65595a618369fb845250
3
+ metadata.gz: 8ca84b456b21332f6eeba63a5667ed1c8cf7ac97d59141192f138d1698c504bf
4
+ data.tar.gz: c380ea14f2ddd44150ae71095063e895486d33077521fe1067fca81d4c4b36b0
5
5
  SHA512:
6
- metadata.gz: fb2609c3dbba1cec025bca22aaa196c718b32084b2954b8184f9b5ce896e7a9289c0b7eb0660469edaf3571d27d99026f6e588f58004e395cee07a75820e38d7
7
- data.tar.gz: 1a87908713cb7dbcb029687dd1d4b9006432e8ba9703ef1dbe813088060c471ada70f8d7d1f5de4cdc9210ba602bd0457b1bf061f6fd3d9a25c5a420003198e0
6
+ metadata.gz: 728dbf1b11115069bb58bfb47c81258f358d22c3570c35dc4a5e7e4d9429a2fa5a6dc3237d0ef0e6a0442d88ca7e9b405e481bd5ea2da90c618800593c8f5155
7
+ data.tar.gz: f014751ea9cf0470fd1387f25f63b56291a63a434abd177ca0e1aaab27ba1d9a4da4e590354b729fcd12a40fa19f125866daedfba4bd904f37e8d48b3c281ea6
data/README.md CHANGED
@@ -68,6 +68,35 @@ See the help for more info:
68
68
 
69
69
  $ bin/rails generate presenter --help
70
70
 
71
+ ### View helpers
72
+
73
+ A presenter can use any helpers via `#helpers` (aliased as `#h`) both in class and instance methods:
74
+
75
+ ```ruby
76
+ class PersonPresenter < Magic::Presenter::Base
77
+ def self.links
78
+ [ h.link_to('All', model_class) ]
79
+ end
80
+
81
+ def link(...)
82
+ helpers.link_to(name, self, ...)
83
+ end
84
+ end
85
+ ```
86
+
87
+ A view context must be set to enable helpers.
88
+ It’s done automagically [wherever possible](#helpers).
89
+ However, one can set it explicitly anywhere:
90
+
91
+ ```ruby
92
+ Magic::Presenter.with view_context: ApplicationController.new.view_context do
93
+ # put the code that uses helpers within presenters here
94
+ end
95
+ ```
96
+
97
+ > [!NOTE]
98
+ > A valid `request` may be needed for URL helpers to get host info.
99
+
71
100
  ## 🧙 Magic
72
101
 
73
102
  It’s based on [Magic Decorator](
@@ -109,6 +138,13 @@ Magic::Presenter.name_for Person # => "PersonPresenter"
109
138
  > Every object passed to views is decorated automagically.
110
139
  > This involves both implicit instance variables and `locals` passed explicitly.
111
140
 
141
+ ### Helpers
142
+
143
+ View context is set automagically to enable helpers:
144
+ - in views,
145
+ - in controller actions,
146
+ - in mailer actions.
147
+
112
148
  ## Development
113
149
 
114
150
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ presenter_context = proc do
4
+ around_action :set_presenter_context
5
+
6
+ private
7
+
8
+ def set_presenter_context(&)
9
+ Magic::Presenter.with view_context:, &
10
+ end
11
+ end
12
+
13
+ ActiveSupport.on_load :action_controller, &presenter_context
14
+ ActiveSupport.on_load :action_mailer, &presenter_context
@@ -1,19 +1,41 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- ActiveSupport.on_load :action_view do
3
+ ActiveSupport.on_load :action_view do # rubocop:disable Metrics/BlockLength
4
4
  concerning :DecoratedAssignments, prepend: true do
5
5
  def assign(assignments, ...)
6
- assignments
7
- .transform_values! &:decorated
6
+ decorate assignments
8
7
 
9
8
  super
10
9
  end
11
10
 
12
11
  def _run(method, template, locals, ...)
13
- locals
14
- .transform_values! &:decorated
12
+ decorate locals
15
13
 
16
14
  super
17
15
  end
16
+
17
+ private
18
+
19
+ def decorate objects
20
+ objects
21
+ .transform_values!(&:decorated)
22
+ end
23
+ end
24
+
25
+ concerning :PresenterContext, prepend: true do
26
+ def in_rendering_context(...)
27
+ Magic::Presenter::Base.with view_context: self do
28
+ super
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def decorate(...)
35
+ super
36
+ .each_value
37
+ .grep(Magic::Presenter::Base)
38
+ .each { _1.view_context = self }
39
+ end
18
40
  end
19
41
  end
@@ -18,6 +18,7 @@ module Magic
18
18
  # up to `ObjectPresenter`.
19
19
  class Base < Decorator::Base
20
20
  include GlobalID if defined? ::GlobalID
21
+ prepend Helpers if defined? ::ActionView
21
22
 
22
23
  class << self
23
24
  def name_for object_class
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Magic
4
+ module Presenter
5
+ module Helpers # :nodoc:
6
+ extend ActiveSupport::Concern
7
+
8
+ # The Magic::Presenter::Helpers::MissingContext exception is
9
+ # raised when no view context to run helpers in has been set.
10
+ class MissingContext < RuntimeError
11
+ def message
12
+ <<~TEXT
13
+ missing view context
14
+ You should set Magic::Presenter.view_context first
15
+ TEXT
16
+ end
17
+ end
18
+
19
+ prepended do
20
+ class_attribute :view_context
21
+ end
22
+
23
+ class_methods do
24
+ include Helpers
25
+
26
+ alias __raise__ raise
27
+ end
28
+
29
+ private
30
+
31
+ def helpers
32
+ view_context or
33
+ __raise__ MissingContext
34
+ end
35
+
36
+ alias_method :h, :helpers
37
+
38
+ def method_missing(method, ...)
39
+ super
40
+ rescue NoMethodError
41
+ __raise__ unless view_context
42
+ __raise__ unless helpers.respond_to? method
43
+
44
+ helpers.send(method, ...)
45
+ end
46
+
47
+ def respond_to_missing?(method, ...)
48
+ super or
49
+ (helpers if view_context).respond_to?(method, ...)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Magic
4
4
  module Presenter
5
- VERSION = '0.3.0'
5
+ VERSION = '0.4.0'
6
6
  end
7
7
  end
@@ -9,13 +9,14 @@ module Magic # :nodoc:
9
9
  # Presentation layer for Rails models
10
10
  module Presenter
11
11
  autoload :Base, 'magic/presenter/base'
12
+ autoload :Helpers, 'magic/presenter/helpers'
12
13
  autoload :GlobalID, 'magic/presenter/global_id'
13
14
  autoload :Generator, 'generators/magic/presenter/generator'
14
15
 
15
- module_function
16
-
17
- def for(...) = Base.for(...)
18
- def name_for(...) = Base.name_for(...)
16
+ singleton_class.delegate *%i[
17
+ for name_for
18
+ view_context view_context=
19
+ ], to: Base
19
20
  end
20
21
 
21
22
  module_function
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: magic-presenter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Senko
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2024-10-27 00:00:00.000000000 Z
10
+ date: 2024-10-29 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: rails
@@ -54,6 +54,7 @@ files:
54
54
  - README.md
55
55
  - Rakefile
56
56
  - app/models/concerns/magic/presentable.rb
57
+ - config/initializers/action_controller.rb
57
58
  - config/initializers/action_view.rb
58
59
  - config/initializers/presentable.rb
59
60
  - config/initializers/rspec.rb
@@ -73,6 +74,7 @@ files:
73
74
  - lib/magic/presenter/base.rb
74
75
  - lib/magic/presenter/engine.rb
75
76
  - lib/magic/presenter/global_id.rb
77
+ - lib/magic/presenter/helpers.rb
76
78
  - lib/magic/presenter/version.rb
77
79
  - lib/tasks/magic/presenter_tasks.rake
78
80
  homepage: https://github.com/Alexander-Senko/magic-presenter
@@ -81,7 +83,7 @@ licenses:
81
83
  metadata:
82
84
  homepage_uri: https://github.com/Alexander-Senko/magic-presenter
83
85
  source_code_uri: https://github.com/Alexander-Senko/magic-presenter
84
- changelog_uri: https://github.com/Alexander-Senko/magic-presenter/blob/v0.3.0/CHANGELOG.md
86
+ changelog_uri: https://github.com/Alexander-Senko/magic-presenter/blob/v0.4.0/CHANGELOG.md
85
87
  rdoc_options: []
86
88
  require_paths:
87
89
  - lib