presentability 0.1.0.pre.20220807214309

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9cb368623de9f8e87b526b7ec806fb7469230df1afc2092d1e83c5c00a134140
4
+ data.tar.gz: a2db6a19a38d9bea3113807df66eea6f5a4ba198647291f8c2269cf5c09e2182
5
+ SHA512:
6
+ metadata.gz: f4a042bd7a2abdb74182c429ab3889a2a9e50765f67676be07c2697a22156e364b48c3e182c9260515c96e99d73b585b4893a332720e63333187a66c976110cc
7
+ data.tar.gz: dd0e2b57e05dc7f1c568ada5e6d5c94dac338f176c233a0d4b1509d9c455bc6d07a1274cfda2b7fe48cb30b4619e9ef6c21f34dc8f76781718c2ed6d5b110ab5
data/History.md ADDED
@@ -0,0 +1,4 @@
1
+ ## v0.0.1 [YYYY-MM-DD] Michael Granger <ged@FaerieMUD.org>
2
+
3
+ Initial release.
4
+
data/LICENSE.txt ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2022, Michael Granger
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+
10
+ 2. Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,124 @@
1
+ # Presentability
2
+
3
+ home
4
+ : https://hg.sr.ht/~ged/Presentability
5
+
6
+ code
7
+ : https://hg.sr.ht/~ged/Presentability
8
+
9
+ github
10
+ : https://github.com/ged/presentability
11
+
12
+ docs
13
+ : https://deveiate.org/code/presentability
14
+
15
+
16
+ ## Description
17
+
18
+ Facade-based presenters with minimal assumptions. This library contains
19
+ utilities for setting up presenters for data classes for things like web
20
+ services, logging output, etc.
21
+
22
+ It is intended to be dead-simple by default, returning a Hash containing
23
+ only the attributes you have intentionally exposed from the subject.
24
+
25
+ # lib/acme/widget.rb
26
+ class Acme::Widget
27
+ attr_accessor :sku,
28
+ :name,
29
+ :unit_price,
30
+ :internal_cost,
31
+ :inventory_count
32
+ end
33
+
34
+ # lib/acme/presenters.rb
35
+ module Acme::Presenters
36
+ extend Presentability
37
+
38
+ presenter_for Acme::Widget do
39
+ expose :sku
40
+ expose :name
41
+ expose :unit_price
42
+ end
43
+ end
44
+
45
+ # lib/acme/service.rb
46
+ class Acme::Service < Some::Webservice::Framework
47
+
48
+ on '/api/widgets/<sku>' do |sku|
49
+ widget = Acme::Widget.lookup( sku )
50
+ content_type 'application/json'
51
+ representation = Acme::Presenters.present( widget )
52
+ return representation.to_json
53
+ end
54
+
55
+ end
56
+
57
+ Note that Presentability doesn't do any encoding for you, or infer anything, or
58
+ require that you alter your data classes. It's just a collection of Facades for
59
+ your data objects that return a limited representation of their subjects.
60
+
61
+ More details can be found in the docs for the Presentability module, and in
62
+ Presentability::Presenter.
63
+
64
+
65
+ ## Prerequisites
66
+
67
+ * Ruby
68
+
69
+
70
+ ## Installation
71
+
72
+ $ gem install presentability
73
+
74
+
75
+ ## Contributing
76
+
77
+ You can check out the current development source with Mercurial via its
78
+ [project page](http://bitbucket.org/ged/presentability). Or if you prefer Git, via
79
+ [its Github mirror](https://github.com/ged/presentability).
80
+
81
+ After checking out the source and changing into the resulting directory, run:
82
+
83
+ $ gem install -Ng
84
+ $ rake setup
85
+
86
+ This will install dependencies, and do any other necessary setup for development.
87
+
88
+
89
+ ## Authors
90
+
91
+ - Michael Granger <ged@faeriemud.org>
92
+
93
+
94
+ ## License
95
+
96
+ Copyright (c) 2022, Michael Granger
97
+ All rights reserved.
98
+
99
+ Redistribution and use in source and binary forms, with or without
100
+ modification, are permitted provided that the following conditions are met:
101
+
102
+ * Redistributions of source code must retain the above copyright notice,
103
+ this list of conditions and the following disclaimer.
104
+
105
+ * Redistributions in binary form must reproduce the above copyright notice,
106
+ this list of conditions and the following disclaimer in the documentation
107
+ and/or other materials provided with the distribution.
108
+
109
+ * Neither the name of the author/s, nor the names of the project's
110
+ contributors may be used to endorse or promote products derived from this
111
+ software without specific prior written permission.
112
+
113
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
114
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
115
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
116
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
117
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
118
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
119
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
120
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
121
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
122
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
123
+
124
+
@@ -0,0 +1,84 @@
1
+ # -*- ruby -*-
2
+ # frozen_string_literal: true
3
+
4
+ require 'loggability'
5
+
6
+ require 'presentability' unless defined?( Presentability )
7
+
8
+
9
+ class Presentability::Presenter
10
+ extend Loggability
11
+
12
+
13
+ # The exposure options used by every exposure unless overridden
14
+ DEFAULT_EXPOSURE_OPTIONS = {}.freeze
15
+
16
+
17
+ # Loggability API; use Presentability's logger
18
+ log_to :presentability
19
+
20
+
21
+ # This is an abstract class; disallow instantiation
22
+ private_class_method :new
23
+
24
+
25
+ ### Enable instantiation by subclasses.
26
+ def self::inherited( subclass )
27
+ super
28
+ subclass.public_class_method( :new )
29
+ subclass.exposures = {}
30
+ end
31
+
32
+
33
+ ##
34
+ # The Hash of exposures declared by this class
35
+ singleton_class.attr_accessor :exposures
36
+
37
+
38
+ ### Set up an exposure that will delegate to the attribute of the subject with
39
+ ### the given +name+.
40
+ def self::expose( name, options={} )
41
+ options = DEFAULT_EXPOSURE_OPTIONS.merge( options )
42
+
43
+ self.log.debug "Setting up exposure %p %p" % [ name, options ]
44
+ self.exposures[ name ] = options
45
+ end
46
+
47
+
48
+ ### Create a new Presenter for the given +subject+.
49
+ def initialize( subject )
50
+ @subject = subject
51
+ end
52
+
53
+
54
+ ######
55
+ public
56
+ ######
57
+
58
+ ##
59
+ # The subject of the presenter, the object that is delegated to when
60
+ # building the representation.
61
+ attr_reader :subject
62
+
63
+
64
+ ### Return a new instance of whatever object type will be used to represent the
65
+ ### subject.
66
+ def empty_representation
67
+ return {}
68
+ end
69
+
70
+
71
+ ### Apply the exposures to the subject and return the result.
72
+ def apply
73
+ result = self.empty_representation
74
+
75
+ self.class.exposures.each do |name, opts|
76
+ # :TODO: #public_send instead?
77
+ value = self.subject.send( name )
78
+ result[ name.to_sym ] = value
79
+ end
80
+
81
+ return result
82
+ end
83
+
84
+ end # class Presentability::Presenter
@@ -0,0 +1,60 @@
1
+ # -*- ruby -*-
2
+ # frozen_string_literal: true
3
+
4
+ require 'loggability'
5
+
6
+
7
+ # Facade-based presenters with minimal assumptions.
8
+ module Presentability
9
+ extend Loggability
10
+
11
+
12
+ # Package version
13
+ VERSION = '0.0.1'
14
+
15
+
16
+ # Automatically load subordinate components
17
+ autoload :Presenter, 'presentability/presenter'
18
+
19
+
20
+ # Create a logger used by all Presentability modules
21
+ log_as :presentability
22
+
23
+
24
+ ### Extension hook -- decorate the including +mod+.
25
+ def self::extended( mod )
26
+ super
27
+ mod.singleton_class.attr_accessor :presenters
28
+ mod.presenters = {}
29
+ end
30
+
31
+
32
+
33
+ ### Set up a presentation for the given +entity_class+.
34
+ def presenter_for( entity_class, &block )
35
+ presenter_class = Class.new( Presentability::Presenter )
36
+ presenter_class.instance_eval( &block )
37
+
38
+ self.presenters[ entity_class ] = presenter_class
39
+ end
40
+
41
+
42
+ ### Return a representation of the +object+ by applying a declared presentation.
43
+ def present( object )
44
+ representation = self.present_by_class( object )
45
+
46
+ return representation
47
+ end
48
+
49
+
50
+ ### Return a representation of the +object+ by applying a presenter declared for its
51
+ ### class. Returns +nil+ if no such presenter exists.
52
+ def present_by_class( object )
53
+ presenter_class = self.presenters[ object.class ] or return nil
54
+ presenter = presenter_class.new( object )
55
+
56
+ return presenter.apply
57
+ end
58
+
59
+ end # module Presentability
60
+
@@ -0,0 +1,48 @@
1
+ # -*- ruby -*-
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'spec_helper'
5
+
6
+ require 'rspec'
7
+ require 'presentability'
8
+
9
+
10
+ RSpec.describe Presentability do
11
+
12
+ let( :entity_class ) do
13
+ Class.new do
14
+ def initialize
15
+ @foo = 1
16
+ @bar = 'two'
17
+ @baz = :three
18
+ end
19
+
20
+ attr_accessor :foo, :bar, :baz
21
+ end
22
+ end
23
+
24
+ let( :entity_instance ) { entity_class.new }
25
+
26
+
27
+ describe "an extended module" do
28
+
29
+ subject do
30
+ mod = Module.new
31
+ mod.extend( described_class )
32
+ end
33
+
34
+
35
+ it "can define a presenter for an explicit class" do
36
+ subject.presenter_for( entity_class ) do
37
+ expose :foo
38
+ expose :bar
39
+ end
40
+
41
+ expect( subject.present(entity_instance) ).to eq({ foo: 1, bar: 'two' })
42
+ end
43
+
44
+
45
+ end
46
+
47
+ end
48
+
@@ -0,0 +1,30 @@
1
+ # -*- ruby -*-
2
+ # frozen_string_literal: true
3
+
4
+ require 'simplecov' if ENV['COVERAGE']
5
+
6
+ require 'rspec'
7
+
8
+ require 'loggability/spechelpers'
9
+
10
+
11
+ ### Mock with RSpec
12
+ RSpec.configure do |config|
13
+ config.mock_with( :rspec ) do |mock|
14
+ mock.syntax = :expect
15
+ end
16
+
17
+ config.disable_monkey_patching!
18
+ config.example_status_persistence_file_path = "spec/.status"
19
+ config.filter_run :focus
20
+ config.filter_run_when_matching :focus
21
+ config.order = :random
22
+ config.profile_examples = 5
23
+ config.run_all_when_everything_filtered = true
24
+ config.shared_context_metadata_behavior = :apply_to_host_groups
25
+ # config.warnings = true
26
+
27
+ config.include( Loggability::SpecHelpers )
28
+ end
29
+
30
+
metadata ADDED
@@ -0,0 +1,85 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: presentability
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.pre.20220807214309
5
+ platform: ruby
6
+ authors:
7
+ - Michael Granger
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-08-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: loggability
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.18'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.18'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake-deveiate
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.19'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.19'
41
+ description: Facade-based presenters with minimal assumptions. This library contains
42
+ utilities for setting up presenters for data classes for things like web services,
43
+ logging output, etc.
44
+ email:
45
+ - ged@faeriemud.org
46
+ executables: []
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - History.md
51
+ - LICENSE.txt
52
+ - README.md
53
+ - lib/presentability.rb
54
+ - lib/presentability/presenter.rb
55
+ - spec/presentability_spec.rb
56
+ - spec/spec_helper.rb
57
+ homepage: https://hg.sr.ht/~ged/Presentability
58
+ licenses:
59
+ - BSD-3-Clause
60
+ metadata:
61
+ bug_tracker_uri: https://todo.sr.ht/~ged/Presentability
62
+ changelog_uri: https://deveiate.org/code/presentability/History_md.html
63
+ documentation_uri: https://deveiate.org/code/presentability
64
+ homepage_uri: https://hg.sr.ht/~ged/Presentability
65
+ source_uri: https://hg.sr.ht/~ged/Presentability
66
+ post_install_message:
67
+ rdoc_options: []
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">"
78
+ - !ruby/object:Gem::Version
79
+ version: 1.3.1
80
+ requirements: []
81
+ rubygems_version: 3.3.7
82
+ signing_key:
83
+ specification_version: 4
84
+ summary: Facade-based presenters with minimal assumptions.
85
+ test_files: []