presentability 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 +4 -4
- checksums.yaml.gz.sig +4 -2
- data/History.md +7 -0
- data/Presentability.md +105 -0
- data/Presenter.md +109 -0
- data/lib/presentability/presenter.rb +8 -35
- data/lib/presentability.rb +3 -65
- data/spec/presentability/presenter_spec.rb +1 -2
- data/spec/presentability_spec.rb +50 -5
- data/spec/spec_helper.rb +8 -2
- data.tar.gz.sig +0 -0
- metadata +17 -15
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 67ea66c2c975ecb5064c9ddb9c0be1a203b0e9e9944dfc3f3821f07e360fc726
|
4
|
+
data.tar.gz: c13fdaccf960dc87d3feaed73e2a22a96ad805aed83cadbadeeee9cc60e80e49
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 550a710c7ae589dfc6ebb1ed801508c8e2d347dbd37e1cdd19e3f3699b5b203ad38b7f2dc6a917e71d3e3dd3711e4eefe8c01594a1f4d92f10b120c4fe1e0a82
|
7
|
+
data.tar.gz: 07d9674d3ad188b6b19923153accddf6175bf61d238d79867b7237a34a10595e066e10f4d37cc702bbcca8b7dcf65fd7df75ad0eb2fa0c4557716be3a370090b
|
checksums.yaml.gz.sig
CHANGED
@@ -1,2 +1,4 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
p�kV��V��H�Nl*�z�K3]<�[�>"��oNP��3O�-ф��ں<�W��ȁî��~������O���������{��a�Z�� c���J�h�a)^\����/�JDMN�f9����
|
2
|
+
/�;!��C
|
3
|
+
���&9u���NI� X��1l7�Po �p�|�T��VI:��t}���E�
|
4
|
+
��| ��I�_gfM��*B7�O�Dw���,��6�v���B?��Ro$��3&���
|
data/History.md
CHANGED
data/Presentability.md
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
|
2
|
+
Facade-based presenter toolkit with minimal assumptions.
|
3
|
+
|
4
|
+
## Basic Usage
|
5
|
+
|
6
|
+
Basic usage of Presentability requires two steps: declaring presenters and
|
7
|
+
then using them.
|
8
|
+
|
9
|
+
### Declaring Presenters
|
10
|
+
|
11
|
+
Presenters are just regular Ruby classes with some convenience methods for
|
12
|
+
declaring exposures, but in a lot of cases you'll want to declare them all in
|
13
|
+
one place. Presentability offers a mixin that implements a simple DSL for
|
14
|
+
declaring presenters and their associations to entity classes, intended to be
|
15
|
+
used in a container module:
|
16
|
+
|
17
|
+
require 'presentability'
|
18
|
+
|
19
|
+
module Acme::Presenters
|
20
|
+
extend Presentability
|
21
|
+
|
22
|
+
presenter_for( Acme::Widget ) do
|
23
|
+
expose :sku
|
24
|
+
expose :name
|
25
|
+
expose :unit_price
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
The block of `presenter_for` is evaluated in the context of a new Presenter
|
31
|
+
class, so refer to that documentation for what's possible there.
|
32
|
+
|
33
|
+
Sometimes you can't (or don't want to) have to load the entity class to
|
34
|
+
declare a presenter for it, so you can also declare it using the class's name:
|
35
|
+
|
36
|
+
presenter_for( 'Acme::Widget' ) do
|
37
|
+
expose :sku
|
38
|
+
expose :name
|
39
|
+
expose :unit_price
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
### Using Presenters
|
44
|
+
|
45
|
+
You use presenters by instantiating them with the object they are a facade for
|
46
|
+
(the "subject"), and then applying it:
|
47
|
+
|
48
|
+
acme_widget = Acme::Widget.new(
|
49
|
+
sku: "FF-2237H455",
|
50
|
+
name: "Throbbing Frobnulator",
|
51
|
+
unit_price: 299,
|
52
|
+
inventory_count: 301,
|
53
|
+
wholesale_cost: 39
|
54
|
+
)
|
55
|
+
presentation = Acme::Presenters.present( acme_widget )
|
56
|
+
# => { :sku => "FF-2237H455", :name => "Throbbing Frobnulator", :unit_price => 299 }
|
57
|
+
|
58
|
+
If you want to present a collection of objects as a collection, you can apply presenters to the collection instead:
|
59
|
+
|
60
|
+
widgets_in_stock = Acme::Widget.where { inventory_count > 0 }
|
61
|
+
collection_presentation = Acme::Presenters.present_collection( widgets_in_stock )
|
62
|
+
# => [ {:sku => "FF-2237H455", [...]}, {:sku => "FF-2237H460", [...]}, [...] ]
|
63
|
+
|
64
|
+
The collection can be anything that is `Enumerable`.
|
65
|
+
|
66
|
+
|
67
|
+
### Presentation Options
|
68
|
+
|
69
|
+
Sometimes you want a bit more flexibility in what you present, allowing a single uniform presenter to be used in multiple use cases. To facilitate this, you can pass an options keyword hash to `#present`:
|
70
|
+
|
71
|
+
presenter_for( 'Acme::Widget' ) do
|
72
|
+
expose :sku
|
73
|
+
expose :name
|
74
|
+
expose :unit_price
|
75
|
+
|
76
|
+
# Only expose the wholesale cost if presented via an internal API
|
77
|
+
expose :wholesale_cost, if: :internal_api
|
78
|
+
end
|
79
|
+
|
80
|
+
acme_widget = Acme::Widget.new(
|
81
|
+
sku: "FF-2237H455",
|
82
|
+
name: "Throbbing Frobnulator",
|
83
|
+
unit_price: 299,
|
84
|
+
inventory_count: 301,
|
85
|
+
wholesale_cost: 39
|
86
|
+
)
|
87
|
+
|
88
|
+
# External API remains unchanged:
|
89
|
+
presentation = Acme::Presenters.present( acme_widget )
|
90
|
+
# => { :sku => "FF-2237H455", :name => "Throbbing Frobnulator", :unit_price => 299 }
|
91
|
+
|
92
|
+
# But when run from an internal service:
|
93
|
+
internal_presentation = Acme::Presenters.present( acme_widget, internal_api: true )
|
94
|
+
# => { :sku => "FF-2237H455", :name => "Throbbing Frobnulator", :unit_price => 299,
|
95
|
+
# :wholesale_cost => 39 }
|
96
|
+
|
97
|
+
There are some options that are set for you:
|
98
|
+
|
99
|
+
<dl>
|
100
|
+
<td><code>:in_collection</code></td>
|
101
|
+
<dd>Set if the current object is being presented as part of a collection.</dd>
|
102
|
+
</dl>
|
103
|
+
|
104
|
+
|
105
|
+
|
data/Presenter.md
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
|
2
|
+
A presenter (facade) base class.
|
3
|
+
|
4
|
+
|
5
|
+
### Declaring Presenters
|
6
|
+
|
7
|
+
When you declare a presenter in a Presentability collection, the result is a
|
8
|
+
subclass of Presentability::Presenter. The main way of defining a Presenter's
|
9
|
+
functionality is via the ::expose method, which marks an attribute of the underlying
|
10
|
+
entity object (the "subject") for exposure.
|
11
|
+
|
12
|
+
class MyPresenter < Presentability::Presenter
|
13
|
+
expose :name
|
14
|
+
end
|
15
|
+
|
16
|
+
# Assuming `entity_object' has a "name" attribute...
|
17
|
+
presenter = MyPresenter.new( entity_object )
|
18
|
+
presenter.apply
|
19
|
+
# => { :name => "entity name" }
|
20
|
+
|
21
|
+
|
22
|
+
### Presenter Collections
|
23
|
+
|
24
|
+
Setting up classes manually like this is one option, but Presentability also lets you
|
25
|
+
set them up as a collection, which is what further examples will assume for brevity:
|
26
|
+
|
27
|
+
module MyPresenters
|
28
|
+
extend Presentability
|
29
|
+
|
30
|
+
presenter_for( EntityObject ) do
|
31
|
+
expose :name
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
### Complex Exposures
|
38
|
+
|
39
|
+
Sometimes you want to do more than just use the presented entity's values as-is. There are a number of ways to do this.
|
40
|
+
|
41
|
+
The first of these is to provide a block when exposing an attribute. The subject of the presenter is available to the block via the `subject` method:
|
42
|
+
|
43
|
+
require 'time'
|
44
|
+
|
45
|
+
presenter_for( LogEvent ) do
|
46
|
+
# Turn Time objects into RFC2822-formatted time strings
|
47
|
+
expose :timestamp do
|
48
|
+
self.subject.timestamp.rfc2822
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
You can also declare the exposure using a regular method with the same name:
|
54
|
+
|
55
|
+
require 'time'
|
56
|
+
|
57
|
+
presenter_for( LogEvent ) do
|
58
|
+
# Turn Time objects into RFC2822-formatted time strings
|
59
|
+
expose :timestamp
|
60
|
+
|
61
|
+
def timestamp
|
62
|
+
return self.subject.timestamp.rfc2822
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
This can be used to add presence checks:
|
68
|
+
|
69
|
+
require 'time'
|
70
|
+
|
71
|
+
presenter_for( LogEvent ) do
|
72
|
+
# Require that presented entities have an `id` attribute
|
73
|
+
expose :id do
|
74
|
+
id = self.subject.id or raise "no `id' for %p" % [ self.subject ]
|
75
|
+
raise "`id' for %p is blank!" % [ self.subject ] if id.blank?
|
76
|
+
|
77
|
+
return id
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
or conditional exposures:
|
82
|
+
|
83
|
+
presenter_for( Acme::Product ) do
|
84
|
+
|
85
|
+
# Truncate the long description if presented as part of a collection
|
86
|
+
expose :detailed_description do
|
87
|
+
desc = self.subject.detailed_description
|
88
|
+
if self.options[:in_collection]
|
89
|
+
return desc[0..15] + '...'
|
90
|
+
else
|
91
|
+
return desc
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
### Exposure Aliases
|
99
|
+
|
100
|
+
If you want to expose a field but use a different name in the resulting data structure, you can use the `:as` option in the exposure declaration:
|
101
|
+
|
102
|
+
presenter_for( LogEvent ) do
|
103
|
+
expose :timestamp, as: :created_at
|
104
|
+
end
|
105
|
+
|
106
|
+
presenter = MyPresenter.new( log_event )
|
107
|
+
presenter.apply
|
108
|
+
# => { :created_at => '2023-02-01 12:34:02.155365 -0800' }
|
109
|
+
|
@@ -1,43 +1,10 @@
|
|
1
1
|
# -*- ruby -*-
|
2
|
-
# frozen_string_literal: true
|
3
2
|
|
4
3
|
require 'loggability'
|
5
4
|
|
6
5
|
require 'presentability' unless defined?( Presentability )
|
7
6
|
|
8
|
-
#
|
9
|
-
# A presenter (facade) base class.
|
10
|
-
#
|
11
|
-
# When you declare a presenter in a Presentability collection, the result is a
|
12
|
-
# subclass of Presentability::Presenter. The main way of defining a Presenter's
|
13
|
-
# functionality is via the ::expose method, which marks an attribute of the underlying
|
14
|
-
# entity object (the "subject") for exposure.
|
15
|
-
#
|
16
|
-
# ```ruby
|
17
|
-
# class MyPresenter < Presentability::Presenter
|
18
|
-
# expose :name
|
19
|
-
# end
|
20
|
-
#
|
21
|
-
# # Assuming `entity_object' has a "name" attribute...
|
22
|
-
# presenter = MyPresenter.new( entity_object )
|
23
|
-
# presenter.apply
|
24
|
-
# # => { :name => "entity name" }
|
25
|
-
# ```
|
26
|
-
#
|
27
|
-
# Setting up classes like this manually is one option, but Presentability also lets you
|
28
|
-
# set them up as a collection, which is what further examples will assume for brevity:
|
29
|
-
#
|
30
|
-
# ```ruby
|
31
|
-
# module MyPresenters
|
32
|
-
# extend Presentability
|
33
|
-
#
|
34
|
-
# presenter_for( EntityObject ) do
|
35
|
-
# expose :name
|
36
|
-
# end
|
37
|
-
#
|
38
|
-
# end
|
39
|
-
# ```
|
40
|
-
#
|
7
|
+
# :include: Presenter.md
|
41
8
|
class Presentability::Presenter
|
42
9
|
extend Loggability
|
43
10
|
|
@@ -63,6 +30,7 @@ class Presentability::Presenter
|
|
63
30
|
|
64
31
|
|
65
32
|
##
|
33
|
+
# :singleton-method: exposures
|
66
34
|
# The Hash of exposures declared by this class
|
67
35
|
singleton_class.attr_accessor :exposures
|
68
36
|
|
@@ -80,6 +48,10 @@ class Presentability::Presenter
|
|
80
48
|
define_method( name, &method_body )
|
81
49
|
end
|
82
50
|
|
51
|
+
if (exposure_alias = options[:as]) && self.exposures.key?( exposure_alias )
|
52
|
+
raise ScriptError, "alias %p collides with another exposure" % [ exposure_alias ]
|
53
|
+
end
|
54
|
+
|
83
55
|
self.log.debug "Setting up exposure %p, options = %p" % [ name, options ]
|
84
56
|
self.exposures[ name ] = options
|
85
57
|
end
|
@@ -141,7 +113,8 @@ class Presentability::Presenter
|
|
141
113
|
self.class.exposures.each do |name, exposure_options|
|
142
114
|
next if self.skip_exposure?( name )
|
143
115
|
value = self.method( name ).call
|
144
|
-
|
116
|
+
key = exposure_options.key?( :as ) ? exposure_options[:as] : name
|
117
|
+
result[ key.to_sym ] = value
|
145
118
|
end
|
146
119
|
|
147
120
|
return result
|
data/lib/presentability.rb
CHANGED
@@ -1,78 +1,15 @@
|
|
1
1
|
# -*- ruby -*-
|
2
|
-
# frozen_string_literal: true
|
3
2
|
|
4
3
|
require 'loggability'
|
5
4
|
|
6
5
|
|
7
|
-
#
|
8
|
-
#
|
9
|
-
# ## Basic Usage
|
10
|
-
#
|
11
|
-
# Basic usage of Presentability requires two steps: declaring presenters and
|
12
|
-
# then using them.
|
13
|
-
#
|
14
|
-
# ### Declaring Presenters
|
15
|
-
#
|
16
|
-
# Presenters are just regular Ruby classes with some convenience methods for
|
17
|
-
# declaring exposures, but in a lot of cases you'll want to declare them all in
|
18
|
-
# one place. Presentability offers a mixin that implements a simple DSL for
|
19
|
-
# declaring presenters and their associations to entity classes, intended to be
|
20
|
-
# used in a container module:
|
21
|
-
#
|
22
|
-
# ```ruby
|
23
|
-
# require 'presentability'
|
24
|
-
#
|
25
|
-
# module Acme::Presenters
|
26
|
-
# extend Presentability
|
27
|
-
#
|
28
|
-
# presenter_for( Acme::Widget ) do
|
29
|
-
# expose :sku
|
30
|
-
# expose :name
|
31
|
-
# expose :unit_price
|
32
|
-
# end
|
33
|
-
#
|
34
|
-
# end
|
35
|
-
# ```
|
36
|
-
#
|
37
|
-
# The block of `presenter_for` is evaluated in the context of a new Presenter
|
38
|
-
# class, so refer to that documentation for what's possible there.
|
39
|
-
#
|
40
|
-
# Sometimes you can't (or don't want to) have to load the entity class to
|
41
|
-
# declare a presenter for it, so you can also declare it using the class's name:
|
42
|
-
#
|
43
|
-
# ```ruby
|
44
|
-
# presenter_for( 'Acme::Widget' ) do
|
45
|
-
# expose :sku
|
46
|
-
# expose :name
|
47
|
-
# expose :unit_price
|
48
|
-
# end
|
49
|
-
# ```
|
50
|
-
#
|
51
|
-
# ### Using Presenters
|
52
|
-
#
|
53
|
-
# You use presenters by instantiating them with the object they are a facade for
|
54
|
-
# (the "subject"), and then applying it:
|
55
|
-
#
|
56
|
-
# ```ruby
|
57
|
-
# acme_widget = Acme::Widget.new(
|
58
|
-
# sku: "FF-2237H455",
|
59
|
-
# name: "Throbbing Frobnulator",
|
60
|
-
# unit_price: 299,
|
61
|
-
# inventory_count: 301,
|
62
|
-
# wholesale_cost: 39
|
63
|
-
# )
|
64
|
-
# presenter = Acme::Presenters.present( acme_widget )
|
65
|
-
# presenter.apply
|
66
|
-
# # => { :sku => "FF-2237H455", :name => "Throbbing Frobnulator", :unit_price => 299 }
|
67
|
-
# ```
|
68
|
-
#
|
69
|
-
#
|
6
|
+
# :include: Presentability.md
|
70
7
|
module Presentability
|
71
8
|
extend Loggability
|
72
9
|
|
73
10
|
|
74
11
|
# Package version
|
75
|
-
VERSION = '0.
|
12
|
+
VERSION = '0.4.0'
|
76
13
|
|
77
14
|
|
78
15
|
# Automatically load subordinate components
|
@@ -114,6 +51,7 @@ module Presentability
|
|
114
51
|
### Return an Array of all representations of the members of the
|
115
52
|
### +collection+ by applying a declared presentation.
|
116
53
|
def present_collection( collection, **options )
|
54
|
+
options = options.merge( in_collection: true )
|
117
55
|
return collection.map {|object| self.present(object, **options) }
|
118
56
|
end
|
119
57
|
|
@@ -1,5 +1,4 @@
|
|
1
1
|
# -*- ruby -*-
|
2
|
-
# frozen_string_literal: true
|
3
2
|
|
4
3
|
require_relative '../spec_helper'
|
5
4
|
|
@@ -21,7 +20,7 @@ RSpec.describe( Presentability::Presenter ) do
|
|
21
20
|
end
|
22
21
|
|
23
22
|
|
24
|
-
describe "
|
23
|
+
describe "concrete subclass" do
|
25
24
|
|
26
25
|
let( :subclass ) { Class.new(described_class) }
|
27
26
|
|
data/spec/presentability_spec.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
# -*- ruby -*-
|
2
|
-
# frozen_string_literal: true
|
3
2
|
|
4
3
|
require_relative 'spec_helper'
|
5
4
|
|
@@ -55,7 +54,7 @@ RSpec.describe Presentability do
|
|
55
54
|
end
|
56
55
|
|
57
56
|
|
58
|
-
describe "
|
57
|
+
describe "when used to extend a module" do
|
59
58
|
|
60
59
|
let( :extended_module ) do
|
61
60
|
mod = Module.new
|
@@ -181,10 +180,38 @@ RSpec.describe Presentability do
|
|
181
180
|
end
|
182
181
|
|
183
182
|
|
183
|
+
it "can alias a field to a different name" do
|
184
|
+
extended_module.presenter_for( entity_class ) do
|
185
|
+
expose :foo, as: :bar
|
186
|
+
end
|
187
|
+
|
188
|
+
expect( extended_module.present(entity_instance) ).to eq({ bar: 1 })
|
189
|
+
end
|
190
|
+
|
191
|
+
|
192
|
+
it "doesn't error when aliasing a field to itself" do
|
193
|
+
extended_module.presenter_for( entity_class ) do
|
194
|
+
expose :foo, as: :foo
|
195
|
+
expose :bar, as: :floom
|
196
|
+
end
|
197
|
+
|
198
|
+
expect( extended_module.present(entity_instance) ).to eq({ foo: 1, floom: 'two' })
|
199
|
+
end
|
200
|
+
|
201
|
+
|
202
|
+
it "raises if an alias clobbers another field" do
|
203
|
+
expect {
|
204
|
+
extended_module.presenter_for( entity_class ) do
|
205
|
+
expose :foo
|
206
|
+
expose :bar, as: :foo
|
207
|
+
end
|
208
|
+
}.to raise_error( ScriptError, /alias :foo collides with another exposure/i )
|
209
|
+
end
|
210
|
+
|
184
211
|
|
185
|
-
describe "collection
|
212
|
+
describe "and used to present a collection" do
|
186
213
|
|
187
|
-
it "
|
214
|
+
it "handles a homogeneous collection" do
|
188
215
|
extended_module.presenter_for( entity_class ) do
|
189
216
|
expose :foo
|
190
217
|
expose :bar
|
@@ -203,7 +230,7 @@ RSpec.describe Presentability do
|
|
203
230
|
end
|
204
231
|
|
205
232
|
|
206
|
-
it "
|
233
|
+
it "handles a hetergeneous collection" do
|
207
234
|
extended_module.presenter_for( entity_class ) do
|
208
235
|
expose :foo
|
209
236
|
expose :bar
|
@@ -260,6 +287,24 @@ RSpec.describe Presentability do
|
|
260
287
|
end
|
261
288
|
end
|
262
289
|
|
290
|
+
|
291
|
+
it "sets the :in_collection option to allow for eliding attributes" do
|
292
|
+
extended_module.presenter_for( entity_class ) do
|
293
|
+
expose :foo
|
294
|
+
expose :bar, unless: :in_collection
|
295
|
+
expose :baz
|
296
|
+
end
|
297
|
+
|
298
|
+
results = extended_module.present_collection( [entity_instance] )
|
299
|
+
|
300
|
+
expect( results.first ).to include( :foo, :baz )
|
301
|
+
expect( results.first ).not_to include( :bar )
|
302
|
+
|
303
|
+
result = extended_module.present( entity_instance )
|
304
|
+
|
305
|
+
expect( result ).to include( :foo, :bar, :baz )
|
306
|
+
end
|
307
|
+
|
263
308
|
end
|
264
309
|
|
265
310
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
# -*- ruby -*-
|
2
|
-
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
3
|
+
if ENV['COVERAGE']
|
4
|
+
require 'simplecov'
|
5
|
+
SimpleCov.start do
|
6
|
+
add_filter 'spec/'
|
7
|
+
enable_coverage :branch
|
8
|
+
primary_coverage :branch
|
9
|
+
end
|
10
|
+
end
|
5
11
|
|
6
12
|
require 'rspec'
|
7
13
|
require 'i18n'
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: presentability
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Granger
|
@@ -10,9 +10,9 @@ bindir: bin
|
|
10
10
|
cert_chain:
|
11
11
|
- |
|
12
12
|
-----BEGIN CERTIFICATE-----
|
13
|
-
MIID+
|
14
|
-
|
15
|
-
|
13
|
+
MIID+DCCAmCgAwIBAgIBBTANBgkqhkiG9w0BAQsFADAiMSAwHgYDVQQDDBdnZWQv
|
14
|
+
REM9RmFlcmllTVVEL0RDPW9yZzAeFw0yMzAxMTYxNzE2MDlaFw0yNDAxMTYxNzE2
|
15
|
+
MDlaMCIxIDAeBgNVBAMMF2dlZC9EQz1GYWVyaWVNVUQvREM9b3JnMIIBojANBgkq
|
16
16
|
hkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAvyVhkRzvlEs0fe7145BYLfN6njX9ih5H
|
17
17
|
L60U0p0euIurpv84op9CNKF9tx+1WKwyQvQP7qFGuZxkSUuWcP/sFhDXL1lWUuIl
|
18
18
|
M4uHbGCRmOshDrF4dgnBeOvkHr1fIhPlJm5FO+Vew8tSQmlDsosxLUx+VB7DrVFO
|
@@ -23,17 +23,17 @@ cert_chain:
|
|
23
23
|
ozilJg4aar2okb/RA6VS87o+d7g6LpDDMMQjH4G9OPnJENLdhu8KnPw/ivSVvQw7
|
24
24
|
N2I4L/ZOIe2DIVuYH7aLHfjZDQv/mNgpAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYD
|
25
25
|
VR0PBAQDAgSwMB0GA1UdDgQWBBRyjf55EbrHagiRLqt5YAd3yb8k4DANBgkqhkiG
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
26
|
+
9w0BAQsFAAOCAYEARYCeUVBWARNKqF0cvNnLJvFf4hdW2+Rtc7NfC5jQvX9a1oom
|
27
|
+
sfVvS96eER/9cbrphu+vc59EELw4zT+RY3/IesnoE7CaX6zIOFmSmG7K61OHsSLR
|
28
|
+
KqMygcWwyuPXT2JG7JsGHuxbzgaRWe29HbSjBbLYxiMH8Zxh4tKutxzKF7jb0Ggq
|
29
|
+
KAf9MH5LwG8IHVIfV5drT14PvgR3tcvmrn1timPyJl+eZ3LNnm9ofOCweuZCq1cy
|
30
|
+
4Q8LV3vP2Cofy9q+az3DHdaUGlmMiZZZqKixDr1KSS9nvh0ZrKMOUL1sWj/IaxrQ
|
31
|
+
RV3y6td14q49t+xnbj00hPlbW7uE2nLJLt2NAoXiE1Nonndz1seB2c6HL79W9fps
|
32
|
+
E/O12pQjCp/aPUZMt8/8tKW31RIy/KP8XO6OTJNWA8A/oNEI0g5p/LmmEtJKWYr1
|
33
|
+
WmEdESlpWhzFECctefIF2lsN9vaOuof57RM77t2otrtcscDtNarIqjZsIyqtDvtL
|
34
|
+
DttITiit0Vwz7bY0
|
35
35
|
-----END CERTIFICATE-----
|
36
|
-
date:
|
36
|
+
date: 2023-02-02 00:00:00.000000000 Z
|
37
37
|
dependencies:
|
38
38
|
- !ruby/object:Gem::Dependency
|
39
39
|
name: loggability
|
@@ -102,6 +102,8 @@ extra_rdoc_files: []
|
|
102
102
|
files:
|
103
103
|
- History.md
|
104
104
|
- LICENSE.txt
|
105
|
+
- Presentability.md
|
106
|
+
- Presenter.md
|
105
107
|
- README.md
|
106
108
|
- lib/presentability.rb
|
107
109
|
- lib/presentability/presenter.rb
|
@@ -132,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
132
134
|
- !ruby/object:Gem::Version
|
133
135
|
version: '0'
|
134
136
|
requirements: []
|
135
|
-
rubygems_version: 3.
|
137
|
+
rubygems_version: 3.4.6
|
136
138
|
signing_key:
|
137
139
|
specification_version: 4
|
138
140
|
summary: Facade-based presenters with minimal assumptions.
|
metadata.gz.sig
CHANGED
Binary file
|