magic-presenter 1.2.0 → 1.3.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/README.md +21 -0
- data/app/models/concerns/magic/presentable/active_record_collection.rb +15 -0
- data/app/models/concerns/magic/presentable/collection.rb +19 -0
- data/app/models/concerns/magic/presentable.rb +2 -0
- data/config/initializers/action_view.rb +10 -0
- data/config/initializers/presentable.rb +4 -0
- data/lib/magic/presenter/base.rb +28 -0
- data/lib/magic/presenter/collection.rb +36 -0
- data/lib/magic/presenter/helpers.rb +2 -1
- data/lib/magic/presenter/version.rb +1 -1
- data/lib/magic/presenter.rb +6 -5
- metadata +7 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0336dc17e983771f6f96385c14429c66e961614ee20f1c99202ab92e970e8663
|
|
4
|
+
data.tar.gz: c923d4f65d8772b8fa52dd62c5d26a0d7b5e96f9d1b3ac12af28296dfb80547b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 94be4b679d87564d79169e919f2e5abb400971b82c0ad78d5456aedbde969e1b4574b27569dee9011861fb899637e3f5394cebfe84488a68063254b70eb7a5a7
|
|
7
|
+
data.tar.gz: 32b20c180e447a2164013d595256c12b8019a5143595d547373c82b157757bea3cf5867248d7068d1d36786e79cd0b6873d6cd814f8f760b53a990c25ed3a924
|
data/README.md
CHANGED
|
@@ -64,6 +64,24 @@ When no presenter is found,
|
|
|
64
64
|
- `#decorate!` raises `Magic::Lookup::Error`,
|
|
65
65
|
- `#decorated` returns the original object.
|
|
66
66
|
|
|
67
|
+
#### Collections
|
|
68
|
+
|
|
69
|
+
Active Record relations are presentable as collections. Define a collection presenter inside the matching presenter to customize collection behavior:
|
|
70
|
+
|
|
71
|
+
```ruby
|
|
72
|
+
class PersonPresenter < Magic::Presenter::Base
|
|
73
|
+
collection_presenter do
|
|
74
|
+
def names = map(&:name).to_sentence
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
Person.all.decorated.names
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Under the hood, `.collection_presenter` defines `PersonPresenter::Collection < Magic::Presenter::Collection` in the above example and evaluates the block within that class’ context.
|
|
82
|
+
It looks for a collection presenter class in ancestor classes to be inherited from, up to `Magic::Presenter::Collection`.
|
|
83
|
+
One can also define a collection presenter class explicitly, following the same pattern.
|
|
84
|
+
|
|
67
85
|
### Generators
|
|
68
86
|
|
|
69
87
|
A generator can be used to generate a presenter:
|
|
@@ -110,6 +128,8 @@ end
|
|
|
110
128
|
> https://github.com/Alexander-Senko/magic-decorator#magic
|
|
111
129
|
> ), so get familiar with that one as well.
|
|
112
130
|
|
|
131
|
+
In short, the phylosophy is: _**define presenters you need and expect them to be applied automagically to all the corresponding objects** in every appropriate (view) context_.
|
|
132
|
+
|
|
113
133
|
### Presentable scope
|
|
114
134
|
|
|
115
135
|
`Magic::Presentable` is mixed into `ActiveModel::API` by default.
|
|
@@ -149,6 +169,7 @@ Missing class methods of a presenter are delegated to a matching model class if
|
|
|
149
169
|
> [!NOTE]
|
|
150
170
|
> Every object passed to views is decorated automagically.
|
|
151
171
|
> This involves both implicit instance variables and `locals` passed explicitly.
|
|
172
|
+
> Controller helper methods are also decorated when called from views.
|
|
152
173
|
|
|
153
174
|
### Helpers
|
|
154
175
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Magic
|
|
4
|
+
module Presentable
|
|
5
|
+
# = Presentable Active Record relation
|
|
6
|
+
#
|
|
7
|
+
# A tiny wrapper around `Presentable::Collection` for Active Record
|
|
8
|
+
# relations.
|
|
9
|
+
module ActiveRecordCollection
|
|
10
|
+
include Collection
|
|
11
|
+
|
|
12
|
+
def model_class = model
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Magic
|
|
4
|
+
module Presentable
|
|
5
|
+
# = Presentable collection
|
|
6
|
+
#
|
|
7
|
+
# This module includes `Magic::Decoratable` and allows a descendant
|
|
8
|
+
# to be decorated by collection presenters only. Presenter class is
|
|
9
|
+
# being inferred automatically from a collection’s model class.
|
|
10
|
+
module Collection
|
|
11
|
+
include Decoratable
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
def decorator = decorator_base.for model_class
|
|
16
|
+
def decorator_base = Presenter::Collection
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -22,6 +22,16 @@ ActiveSupport.on_load :action_view do # rubocop:disable Metrics/BlockLength
|
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
concerning :DecoratedHelpers, prepend: true do
|
|
26
|
+
require 'magic/decorator/core_ext/module'
|
|
27
|
+
|
|
28
|
+
def assign_controller controller
|
|
29
|
+
super
|
|
30
|
+
|
|
31
|
+
self.class.decorated_method controller._helper_methods
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
25
35
|
concerning :PresenterContext, prepend: true do
|
|
26
36
|
def in_rendering_context(...)
|
|
27
37
|
Magic::Presenter.with view_context: self do
|
data/lib/magic/presenter/base.rb
CHANGED
|
@@ -18,6 +18,8 @@ module Magic
|
|
|
18
18
|
include GlobalID if defined? ::GlobalID
|
|
19
19
|
prepend Helpers if defined? ::ActionView
|
|
20
20
|
|
|
21
|
+
Collection = Collection # for lookup
|
|
22
|
+
|
|
21
23
|
class << self
|
|
22
24
|
def name_for object_class
|
|
23
25
|
object_class
|
|
@@ -30,6 +32,32 @@ module Magic
|
|
|
30
32
|
def model_class = Presentable.for self
|
|
31
33
|
|
|
32
34
|
delegate_missing_to :model_class
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
# Define collection presenter from the given block.
|
|
39
|
+
#
|
|
40
|
+
# class MyPresenter < Magic::Presenter::Base
|
|
41
|
+
# collection_presenter do
|
|
42
|
+
# def count = "#{super} items"
|
|
43
|
+
# end
|
|
44
|
+
# end
|
|
45
|
+
#
|
|
46
|
+
# class MyModel < ApplicationRecord
|
|
47
|
+
# end
|
|
48
|
+
#
|
|
49
|
+
# MyModel.all.count # => 42
|
|
50
|
+
# MyModel.all.decorated.count # => "42 items"
|
|
51
|
+
#
|
|
52
|
+
# It looks for a collection presenter class in ancestor classes
|
|
53
|
+
# to be inherited from, up to `Magic::Presenter::Collection`.
|
|
54
|
+
def collection_presenter(&)
|
|
55
|
+
if const_defined? :Collection, false
|
|
56
|
+
const_get :Collection
|
|
57
|
+
else
|
|
58
|
+
const_set :Collection, Class.new(const_get :Collection)
|
|
59
|
+
end.class_eval(&)
|
|
60
|
+
end
|
|
33
61
|
end
|
|
34
62
|
end
|
|
35
63
|
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Magic
|
|
4
|
+
module Presenter
|
|
5
|
+
# = Collection presenter
|
|
6
|
+
#
|
|
7
|
+
# This presenter is used as a base class to decorate typed
|
|
8
|
+
# collections (e.g., Active Record relations).
|
|
9
|
+
#
|
|
10
|
+
# == Presenter class inference
|
|
11
|
+
#
|
|
12
|
+
# Collection presenters provide automatic class inference for any
|
|
13
|
+
# typed collection based on the class name of its elements powered
|
|
14
|
+
# by Magic Lookup.
|
|
15
|
+
# For example, a collection of `MyRecord`s (e.g., `MyRecord.all`)
|
|
16
|
+
# looks for `MyPresenter::Collection` first.
|
|
17
|
+
# If not found, it looks for collection presenters of its ancestor
|
|
18
|
+
# classes, up to `ObjectPresenter::Collection`.
|
|
19
|
+
class Collection < EnumerableDecorator
|
|
20
|
+
prepend Helpers if defined? ::ActionView
|
|
21
|
+
|
|
22
|
+
class << self
|
|
23
|
+
def name_for(...) = Base.name_for(...)
|
|
24
|
+
.concat('::Collection')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def item_presenter = model_class
|
|
28
|
+
&.then { Presenter.for it }
|
|
29
|
+
|
|
30
|
+
def model_class = __getobj__
|
|
31
|
+
.try :model_class
|
|
32
|
+
|
|
33
|
+
def to_a(...) = self.class.new super
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
data/lib/magic/presenter.rb
CHANGED
|
@@ -8,11 +8,12 @@ require_relative 'presenter/engine'
|
|
|
8
8
|
module Magic # :nodoc:
|
|
9
9
|
# Presentation layer for Rails models
|
|
10
10
|
module Presenter
|
|
11
|
-
autoload :Base,
|
|
12
|
-
autoload :
|
|
13
|
-
autoload :
|
|
14
|
-
autoload :
|
|
15
|
-
autoload :
|
|
11
|
+
autoload :Base, 'magic/presenter/base'
|
|
12
|
+
autoload :Collection, 'magic/presenter/collection'
|
|
13
|
+
autoload :Helpers, 'magic/presenter/helpers'
|
|
14
|
+
autoload :GlobalID, 'magic/presenter/global_id'
|
|
15
|
+
autoload :TestCase, 'magic/presenter/test_case'
|
|
16
|
+
autoload :Generator, 'generators/magic/presenter/generator'
|
|
16
17
|
|
|
17
18
|
singleton_class.delegate *%i[
|
|
18
19
|
for name_for
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: magic-presenter
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alexander Senko
|
|
@@ -40,7 +40,7 @@ dependencies:
|
|
|
40
40
|
-
|
|
41
41
|
- ~>
|
|
42
42
|
- !ruby/object:Gem::Version
|
|
43
|
-
version: "1.
|
|
43
|
+
version: "1.2"
|
|
44
44
|
type: :runtime
|
|
45
45
|
prerelease: false
|
|
46
46
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -48,7 +48,7 @@ dependencies:
|
|
|
48
48
|
-
|
|
49
49
|
- ~>
|
|
50
50
|
- !ruby/object:Gem::Version
|
|
51
|
-
version: "1.
|
|
51
|
+
version: "1.2"
|
|
52
52
|
- !ruby/object:Gem::Dependency
|
|
53
53
|
name: magic-lookup
|
|
54
54
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -76,6 +76,8 @@ files:
|
|
|
76
76
|
- README.md
|
|
77
77
|
- Rakefile
|
|
78
78
|
- app/models/concerns/magic/presentable.rb
|
|
79
|
+
- app/models/concerns/magic/presentable/active_record_collection.rb
|
|
80
|
+
- app/models/concerns/magic/presentable/collection.rb
|
|
79
81
|
- config/initializers/action_controller.rb
|
|
80
82
|
- config/initializers/action_view.rb
|
|
81
83
|
- config/initializers/generators.rb
|
|
@@ -95,6 +97,7 @@ files:
|
|
|
95
97
|
- lib/magic/presenter.rb
|
|
96
98
|
- lib/magic/presenter/authors.rb
|
|
97
99
|
- lib/magic/presenter/base.rb
|
|
100
|
+
- lib/magic/presenter/collection.rb
|
|
98
101
|
- lib/magic/presenter/engine.rb
|
|
99
102
|
- lib/magic/presenter/global_id.rb
|
|
100
103
|
- lib/magic/presenter/helpers.rb
|
|
@@ -108,7 +111,7 @@ licenses:
|
|
|
108
111
|
metadata:
|
|
109
112
|
homepage_uri: "https://github.com/Alexander-Senko/magic-presenter"
|
|
110
113
|
source_code_uri: "https://github.com/Alexander-Senko/magic-presenter"
|
|
111
|
-
changelog_uri: "https://github.com/Alexander-Senko/magic-presenter/blob/v1.
|
|
114
|
+
changelog_uri: "https://github.com/Alexander-Senko/magic-presenter/blob/v1.3.0/CHANGELOG.md"
|
|
112
115
|
rdoc_options: []
|
|
113
116
|
require_paths:
|
|
114
117
|
- lib
|