display_case 0.0.7 → 0.0.8
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.
- data/README.md +16 -14
- data/lib/display_case/configuration.rb +8 -0
- data/lib/display_case/exhibit.rb +17 -5
- data/lib/display_case/railtie.rb +1 -1
- metadata +2 -2
data/README.md
CHANGED
@@ -9,7 +9,7 @@ If the Model is concerned with storing and manipulating business data, and the V
|
|
9
9
|
|
10
10
|
The Exhibit object is so named because it is like a museum display case for an artifact or a work of art. It does not obscure any of the features of the object being presented. Rather, it tries to showcase the object in the best light to a human audience, while also presenting meta-information about the object and cross-references to other objects in the museum's collection.
|
11
11
|
|
12
|
-
Technically, exhibit objects are a type of Decorator specialized for presenting models to an end user.
|
12
|
+
Technically, exhibit objects are a type of Decorator specialized for presenting models to an end user.
|
13
13
|
|
14
14
|
For the purposes of clarity, here's a rundown of the essential characteristics of an Exhibit object.
|
15
15
|
|
@@ -32,10 +32,10 @@ Your exhibits will look something like this:
|
|
32
32
|
# app/exhibits/league_exhibit.rb
|
33
33
|
|
34
34
|
class LeagueExhibit < DisplayCase::Exhibit
|
35
|
-
def self.applicable_to?(object, context)
|
35
|
+
def self.applicable_to?(object, context)
|
36
36
|
object.class.name == 'League'
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
def render_icon(template)
|
40
40
|
template.render(partial: 'leagues/icon', locals: {league: self})
|
41
41
|
end
|
@@ -49,11 +49,11 @@ class LeaguesController < ApplicationController
|
|
49
49
|
include DisplayCase::ExhibitsHelper
|
50
50
|
# ...
|
51
51
|
def index
|
52
|
-
# display_case automatically wraps the individual objects contained in
|
52
|
+
# display_case automatically wraps the individual objects contained in
|
53
53
|
# an Enumerable or ActiveRecord::Relation collections
|
54
|
-
@leagues = exhibit(League.all)
|
54
|
+
@leagues = exhibit(League.all)
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
def show
|
58
58
|
# of course it will also wrap your individual objects
|
59
59
|
@league = exhibit(League.find(params[:id]))
|
@@ -64,7 +64,7 @@ end
|
|
64
64
|
Finally, in your view, you can use your Exhibit:
|
65
65
|
```
|
66
66
|
<!-- app/views/leagues/index.html.erb -->
|
67
|
-
<% @leagues.each do |league| %>
|
67
|
+
<% @leagues.each do |league| %>
|
68
68
|
<%= league.render_icon(self) %> <!-- self is this "template", the parameter to the method we defined in LeagueExhibit -->
|
69
69
|
<% end %>
|
70
70
|
```
|
@@ -77,6 +77,7 @@ Several configuration options can be set via an initializer:
|
|
77
77
|
1. `explicit` By default this option is false and Exhibits will be dynamically added via the inherited callback.
|
78
78
|
1. `exhibits` If `explicit` is true you must explicitly set the Exhibits you wish to use in the order you want them evaluated. You can set `config.exhibits = [AnExhibit,AnotherExhibit]` in your initializers/display_case.rb.
|
79
79
|
1. `cache_store` If you configure a cache store, you can use it by calling the `cache` method in your Exhibits (see below).
|
80
|
+
1. `logging_enabled` Setting this to `true` will provide debug information about exhibits to the Rails logger, but may adversely affect performance when many objects are being exhibited.
|
80
81
|
|
81
82
|
An example `initializers/display_case.rb`
|
82
83
|
```
|
@@ -85,26 +86,27 @@ DisplayCase.configure do |config|
|
|
85
86
|
config.explicit = true
|
86
87
|
config.exhibits = [MyFirstExhibit,MySecondExhibit]
|
87
88
|
config.cache_store = Rails.configuration.action_controller.perform_caching ? Rails.cache : nil
|
89
|
+
config.logging_enabled = false
|
88
90
|
end
|
89
91
|
```
|
90
92
|
|
91
93
|
Caching
|
92
94
|
-------
|
93
95
|
You can cache the results of an operation in your exhibits by configuring DisplayCase to use a cache store, and then using the `cache` method.
|
94
|
-
If you do this, you ought not use a real cache in development mode, since you'll likely want to see changes you're making to code, which of
|
96
|
+
If you do this, you ought not use a real cache in development mode, since you'll likely want to see changes you're making to code, which of
|
95
97
|
course won't happen if you cache the results.
|
96
98
|
|
97
|
-
Use the cache like you would in a Rails controller:
|
99
|
+
Use the cache like you would in a Rails controller:
|
98
100
|
|
99
101
|
```ruby
|
100
102
|
class LeagueExhibit < DisplayCase::Exhibit
|
101
|
-
def self.applicable_to?(object, context)
|
103
|
+
def self.applicable_to?(object, context)
|
102
104
|
object.class.name == 'League'
|
103
105
|
end
|
104
|
-
|
106
|
+
|
105
107
|
def render(context)
|
106
|
-
cache key, options={} do
|
107
|
-
# something that takes a long while, which might make you want
|
108
|
+
cache key, options={} do
|
109
|
+
# something that takes a long while, which might make you want
|
108
110
|
# to cache this call to render
|
109
111
|
context.render(partial: 'leagues/icon', locals: {league: self})
|
110
112
|
end
|
@@ -117,4 +119,4 @@ how to choose good keys.
|
|
117
119
|
|
118
120
|
Wrong url with extra parameters using an exhibited model?
|
119
121
|
------------------
|
120
|
-
See this issue for the reason: https://github.com/objects-on-rails/display-case/issues/8
|
122
|
+
See this issue for the reason: https://github.com/objects-on-rails/display-case/issues/8
|
@@ -24,17 +24,25 @@ module DisplayCase
|
|
24
24
|
# A cache store which responds to `fetch(key, options, &block)`
|
25
25
|
attr_accessor :cache_store
|
26
26
|
|
27
|
+
# A boolean indicating whether or not to log to the Rails logger
|
28
|
+
attr_accessor :logging_enabled
|
29
|
+
|
27
30
|
def initialize
|
28
31
|
@definition_file_paths = %w(app/exhibits)
|
29
32
|
@explicit = false
|
30
33
|
@exhibits = []
|
31
34
|
@cache_store = nil
|
35
|
+
@logging_enabled = false
|
32
36
|
end
|
33
37
|
|
34
38
|
def explicit?
|
35
39
|
explicit
|
36
40
|
end
|
37
41
|
|
42
|
+
def logging_enabled?
|
43
|
+
defined? ::Rails and logging_enabled
|
44
|
+
end
|
45
|
+
|
38
46
|
def exhibits
|
39
47
|
[DisplayCase::Exhibit::Exhibited,DisplayCase::BasicExhibit,DisplayCase::EnumerableExhibit] + @exhibits
|
40
48
|
end
|
data/lib/display_case/exhibit.rb
CHANGED
@@ -23,20 +23,32 @@ module DisplayCase
|
|
23
23
|
|
24
24
|
def self.exhibit(object, context=nil)
|
25
25
|
return object if exhibited_object?(object)
|
26
|
-
if
|
26
|
+
if DisplayCase.configuration.logging_enabled?
|
27
27
|
::Rails.logger.debug "Registered exhibits: #{@@exhibits}"
|
28
28
|
::Rails.logger.debug "Exhibiting #{object.inspect}"
|
29
29
|
::Rails.logger.debug "Exhibit context: #{context}"
|
30
30
|
end
|
31
31
|
|
32
|
-
similar, unsimilar = exhibits.partition { |exhibit_class| context and exhibit_class.name and context.class.name and context.class.name.downcase.include?(exhibit_class.name.to_s.downcase.gsub("exhibit", "")) }
|
33
32
|
object = BasicExhibit.new(Exhibited.new(object, context), context)
|
34
|
-
|
35
|
-
|
33
|
+
similar, unsimilar = partition_by_name(exhibits, context)
|
34
|
+
|
35
|
+
# done w/ unsimilar first since the last applied exhibit is the top-most one
|
36
|
+
(unsimilar + similar).inject(object) do |object, exhibit_class|
|
37
|
+
exhibit_class.exhibit_if_applicable(object, context)
|
36
38
|
end.tap do |obj|
|
37
|
-
::Rails.logger.debug "Exhibits applied: #{obj.inspect_exhibits}" if
|
39
|
+
::Rails.logger.debug "Exhibits applied: #{obj.inspect_exhibits}" if DisplayCase.configuration.logging_enabled?
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.partition_by_name(exhibits, context=nil)
|
44
|
+
return [], exhibits if DisplayCase.configuration.explicit? || context.nil? || context.class.name.nil?
|
45
|
+
|
46
|
+
exhibits.partition do |exhibit_class|
|
47
|
+
exhibit_name = exhibit_class.name.to_s.downcase.gsub("exhibit", "")
|
48
|
+
exhibit_name.length > 0 && context.class.name.downcase.include?(exhibit_name)
|
38
49
|
end
|
39
50
|
end
|
51
|
+
private_class_method :partition_by_name
|
40
52
|
|
41
53
|
def self.exhibit_if_applicable(object, context)
|
42
54
|
if applicable_to?(object, context)
|
data/lib/display_case/railtie.rb
CHANGED
@@ -3,7 +3,7 @@ module DisplayCase
|
|
3
3
|
# http://guides.rubyonrails.org/configuring.html#initialization-events
|
4
4
|
# "to_prepare will run upon every request in development, but only once (during boot-up) in production and test."
|
5
5
|
config.to_prepare do
|
6
|
-
DisplayCase.find_definitions if Rails.env.development?
|
6
|
+
DisplayCase.find_definitions if Rails.env.development? || Rails.env.test?
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: display_case
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-07-13 00:00:00.000000000Z
|
13
13
|
dependencies: []
|
14
14
|
description: An implementation of the Exhibit pattern, as described in Objects on
|
15
15
|
Rails
|