display_case 0.0.5 → 0.0.6
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 +3 -1
- data/lib/display_case/basic_exhibit.rb +18 -0
- data/lib/display_case/configuration.rb +3 -3
- data/lib/display_case/enumerable_exhibit.rb +5 -4
- data/lib/display_case/exhibit.rb +45 -35
- data/lib/display_case/is_a_class_comparator.rb +38 -0
- data/lib/display_case/name_class_comparator.rb +13 -0
- data/lib/display_case.rb +1 -0
- metadata +6 -3
data/README.md
CHANGED
@@ -32,7 +32,9 @@ Your exhibits will look something like this:
|
|
32
32
|
# app/exhibits/league_exhibit.rb
|
33
33
|
|
34
34
|
class LeagueExhibit < DisplayCase::Exhibit
|
35
|
-
|
35
|
+
# Note: the context parameter is new in the master branch, not yet released in the gem.
|
36
|
+
# If you get an argument error, that's why
|
37
|
+
def self.applicable_to?(object, context)
|
36
38
|
object.class.name == 'League'
|
37
39
|
end
|
38
40
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative 'exhibit'
|
2
|
+
|
3
|
+
module DisplayCase
|
4
|
+
class BasicExhibit < Exhibit
|
5
|
+
def to_partial_path
|
6
|
+
if __getobj__.respond_to?(:to_partial_path)
|
7
|
+
__getobj__.to_partial_path.dup
|
8
|
+
else
|
9
|
+
partialize_name(__getobj__.class.name)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def render(template)
|
14
|
+
template.render(:partial => to_partial_path, :object => self)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -15,7 +15,7 @@ module DisplayCase
|
|
15
15
|
# dynamically collected with the inherited callback. By default, this is false
|
16
16
|
# and the list will be generated via the inherited callback.
|
17
17
|
attr_accessor :explicit
|
18
|
-
|
18
|
+
|
19
19
|
# An Array of strings specifying locations that should be searched for
|
20
20
|
# exhibit classes and definitions. By default, "/app/exhibits" will be searched and
|
21
21
|
# existing file will be loaded.
|
@@ -32,7 +32,7 @@ module DisplayCase
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def exhibits
|
35
|
-
[DisplayCase::Exhibit::Exhibited,DisplayCase::EnumerableExhibit] + @exhibits
|
35
|
+
[DisplayCase::Exhibit::Exhibited,DisplayCase::BasicExhibit,DisplayCase::EnumerableExhibit] + @exhibits
|
36
36
|
end
|
37
37
|
|
38
38
|
def exhibits=(val)
|
@@ -41,4 +41,4 @@ module DisplayCase
|
|
41
41
|
end
|
42
42
|
|
43
43
|
configure {}
|
44
|
-
end
|
44
|
+
end
|
@@ -4,7 +4,7 @@ module DisplayCase
|
|
4
4
|
class EnumerableExhibit < Exhibit
|
5
5
|
include Enumerable
|
6
6
|
|
7
|
-
def self.applicable_to?(object)
|
7
|
+
def self.applicable_to?(object, context=nil)
|
8
8
|
# ActiveRecord::Relation, surprisingly, is not Enumerable. But it
|
9
9
|
# behaves sufficiently similarly for our purposes.
|
10
10
|
object_is_any_of?(object, 'Enumerable', 'ActiveRecord::Relation')
|
@@ -34,9 +34,10 @@ module DisplayCase
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def each(*)
|
37
|
-
|
38
|
-
yield exhibit(e)
|
39
|
-
|
37
|
+
__getobj__.map do |e|
|
38
|
+
yield exhibit(e) if block_given?
|
39
|
+
exhibit(e)
|
40
|
+
end.each
|
40
41
|
end
|
41
42
|
|
42
43
|
# `render '...', :collection => self` will call #to_ary on this
|
data/lib/display_case/exhibit.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
require 'delegate'
|
2
2
|
require 'active_support/core_ext'
|
3
|
-
require 'display_case/railtie' if defined?(Rails)
|
3
|
+
require 'display_case/railtie' if defined?(::Rails)
|
4
4
|
require_relative 'configuration'
|
5
|
+
require_relative 'is_a_class_comparator'
|
6
|
+
require_relative 'name_class_comparator'
|
5
7
|
|
6
8
|
module DisplayCase
|
7
9
|
class Exhibit < SimpleDelegator
|
8
10
|
@@exhibits = []
|
9
|
-
|
11
|
+
|
10
12
|
def self.exhibits
|
11
13
|
if DisplayCase.configuration.explicit?
|
12
14
|
DisplayCase.configuration.exhibits
|
@@ -14,36 +16,36 @@ module DisplayCase
|
|
14
16
|
@@exhibits
|
15
17
|
end
|
16
18
|
end
|
17
|
-
|
19
|
+
|
18
20
|
def self.inherited(child)
|
19
21
|
@@exhibits << child
|
20
22
|
end
|
21
23
|
|
22
|
-
def self.exhibit(object, context)
|
24
|
+
def self.exhibit(object, context=nil)
|
23
25
|
return object if exhibited_object?(object)
|
24
|
-
if defined? Rails
|
25
|
-
Rails.logger.debug "Registered exhibits: #{@@exhibits}"
|
26
|
-
Rails.logger.debug "Exhibiting #{object.inspect}"
|
27
|
-
Rails.logger.debug "Exhibit context: #{context}"
|
26
|
+
if defined? ::Rails
|
27
|
+
::Rails.logger.debug "Registered exhibits: #{@@exhibits}"
|
28
|
+
::Rails.logger.debug "Exhibiting #{object.inspect}"
|
29
|
+
::Rails.logger.debug "Exhibit context: #{context}"
|
28
30
|
end
|
29
|
-
|
30
|
-
object = Exhibited.new(object, context)
|
31
|
+
|
32
|
+
object = BasicExhibit.new(Exhibited.new(object, context), context)
|
31
33
|
exhibits.inject(object) do |object, exhibit_class|
|
32
34
|
exhibit_class.exhibit_if_applicable(object, context)
|
33
35
|
end.tap do |obj|
|
34
|
-
Rails.logger.debug "Exhibits applied: #{obj.inspect_exhibits}" if defined? Rails
|
36
|
+
::Rails.logger.debug "Exhibits applied: #{obj.inspect_exhibits}" if defined? ::Rails
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
38
40
|
def self.exhibit_if_applicable(object, context)
|
39
|
-
if applicable_to?(object)
|
41
|
+
if applicable_to?(object, context)
|
40
42
|
new(object, context)
|
41
43
|
else
|
42
44
|
object
|
43
45
|
end
|
44
46
|
end
|
45
47
|
|
46
|
-
def self.applicable_to?(object)
|
48
|
+
def self.applicable_to?(object, context=nil)
|
47
49
|
false
|
48
50
|
end
|
49
51
|
|
@@ -60,18 +62,25 @@ module DisplayCase
|
|
60
62
|
end
|
61
63
|
private_class_method :exhibit_query
|
62
64
|
|
65
|
+
def self.class_comparator
|
66
|
+
@@class_comparator ||= begin
|
67
|
+
comparator = nil
|
68
|
+
|
69
|
+
if defined? ::Rails
|
70
|
+
config = ::Rails.respond_to?(:config) ? ::Rails.config : ::Rails.application.config
|
71
|
+
comparator = NameClassComparator.new unless config.cache_classes
|
72
|
+
end
|
73
|
+
|
74
|
+
comparator || IsAClassComparator.new
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
63
78
|
# A helper for matching models to classes/modules, intended for use
|
64
79
|
# in .applicable_to?.
|
65
80
|
def self.object_is_any_of?(object, *classes)
|
66
|
-
|
67
|
-
# unreliable, plus wanting to avoid adding dependencies to
|
68
|
-
# external class definitions if we can avoid it, we just match
|
69
|
-
# against class/module name strings rather than the actual class
|
70
|
-
# objects.
|
71
|
-
|
72
|
-
# Note that '&' is the set intersection operator for Arrays.
|
73
|
-
(classes.map(&:to_s) & object.class.ancestors.map(&:name)).any?
|
81
|
+
self.class_comparator.call(object, *classes)
|
74
82
|
end
|
83
|
+
|
75
84
|
private_class_method :object_is_any_of?
|
76
85
|
|
77
86
|
attr_reader :context
|
@@ -85,25 +94,26 @@ module DisplayCase
|
|
85
94
|
def class
|
86
95
|
__getobj__.class
|
87
96
|
end
|
88
|
-
|
89
|
-
|
90
|
-
|
97
|
+
|
98
|
+
alias_method :__kind_of__?, :kind_of?
|
99
|
+
def kind_of?(klass)
|
100
|
+
__getobj__.kind_of?(klass)
|
91
101
|
end
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
102
|
+
|
103
|
+
alias_method :__is_a__?, :is_a?
|
104
|
+
alias_method :is_a?, :kind_of?
|
105
|
+
|
106
|
+
alias_method :__instance_of__?, :instance_of?
|
107
|
+
def instance_of?(klass)
|
108
|
+
__getobj__.instance_of?(klass)
|
99
109
|
end
|
100
110
|
|
101
|
-
def
|
102
|
-
|
111
|
+
def exhibit(model)
|
112
|
+
Exhibit.exhibit(model, context)
|
103
113
|
end
|
104
114
|
|
105
115
|
def exhibit_chain
|
106
|
-
inner_exhibits =
|
116
|
+
inner_exhibits = __getobj__.respond_to?(:exhibit_chain) ? __getobj__.exhibit_chain : []
|
107
117
|
[__class__] + inner_exhibits
|
108
118
|
end
|
109
119
|
|
@@ -137,4 +147,4 @@ module DisplayCase
|
|
137
147
|
"/#{name.underscore.pluralize}/#{name.demodulize.underscore}"
|
138
148
|
end
|
139
149
|
end
|
140
|
-
end
|
150
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module DisplayCase
|
2
|
+
class IsAClassComparator
|
3
|
+
def call(object, *classes)
|
4
|
+
classes.any?{|klass| object.is_a?(class_object(klass))}
|
5
|
+
end
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
# A simple memoizing class name tracker
|
10
|
+
class ClassTracker
|
11
|
+
def initialize
|
12
|
+
@context = Object
|
13
|
+
@data = Hash.new {|h, k| h[k] = constantize(k)}
|
14
|
+
end
|
15
|
+
|
16
|
+
def class_for(class_name)
|
17
|
+
@data[class_name]
|
18
|
+
end
|
19
|
+
|
20
|
+
def constantize(class_name)
|
21
|
+
return class_name if Module === class_name
|
22
|
+
class_name.to_s.split('::').inject(@context){|context, name|
|
23
|
+
context.const_get(name)
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# holds a reference to the tracker
|
29
|
+
def class_tracker
|
30
|
+
@class_tracker ||= ClassTracker.new
|
31
|
+
end
|
32
|
+
|
33
|
+
# helper method for object_is_any_of to use
|
34
|
+
def class_object(cls)
|
35
|
+
class_tracker.class_for(cls)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module DisplayCase
|
2
|
+
# What with Rails development mode reloading making class matching
|
3
|
+
# unreliable, plus wanting to avoid adding dependencies to external
|
4
|
+
# class definitions if we can avoid it, this class just matches
|
5
|
+
# against class/module name strings rather than the actual class
|
6
|
+
# objects.
|
7
|
+
class NameClassComparator
|
8
|
+
def call(object, *classes)
|
9
|
+
# Note that '&' is the set intersection operator for Arrays.
|
10
|
+
(classes.map(&:to_s) & object.class.ancestors.map(&:name)).any?
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/display_case.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require_relative 'display_case/configuration'
|
2
2
|
require_relative 'display_case/exhibit'
|
3
3
|
require_relative 'display_case/enumerable_exhibit'
|
4
|
+
require_relative 'display_case/basic_exhibit'
|
4
5
|
require_relative 'display_case/exhibits_helper'
|
5
6
|
require_relative 'display_case/find_definitions'
|
6
7
|
|
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.6
|
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:
|
12
|
+
date: 2013-02-14 00:00:00.000000000Z
|
13
13
|
dependencies: []
|
14
14
|
description: An implementation of the Exhibit pattern, as described in Objects on
|
15
15
|
Rails
|
@@ -19,11 +19,14 @@ executables: []
|
|
19
19
|
extensions: []
|
20
20
|
extra_rdoc_files: []
|
21
21
|
files:
|
22
|
+
- lib/display_case/basic_exhibit.rb
|
22
23
|
- lib/display_case/configuration.rb
|
23
24
|
- lib/display_case/enumerable_exhibit.rb
|
24
25
|
- lib/display_case/exhibit.rb
|
25
26
|
- lib/display_case/exhibits_helper.rb
|
26
27
|
- lib/display_case/find_definitions.rb
|
28
|
+
- lib/display_case/is_a_class_comparator.rb
|
29
|
+
- lib/display_case/name_class_comparator.rb
|
27
30
|
- lib/display_case/railtie.rb
|
28
31
|
- lib/display_case.rb
|
29
32
|
- LICENSE
|
@@ -48,7 +51,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
48
51
|
version: '0'
|
49
52
|
requirements: []
|
50
53
|
rubyforge_project:
|
51
|
-
rubygems_version: 1.8.
|
54
|
+
rubygems_version: 1.8.8
|
52
55
|
signing_key:
|
53
56
|
specification_version: 3
|
54
57
|
summary: An implementation of the Exhibit pattern, as described in Objects on Rails
|