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