display_case 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2012 Avdi Grimm
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,4 @@
1
+ display_case
2
+ ============
3
+
4
+ An implementation of the Exhibit pattern, as described in Objects on Rails
File without changes
@@ -0,0 +1,53 @@
1
+ require_relative 'exhibit'
2
+
3
+ class EnumerableExhibit < Exhibit
4
+ include Enumerable
5
+
6
+ def self.applicable_to?(object)
7
+ # ActiveRecord::Relation, surprisingly, is not Enumerable. But it
8
+ # behaves sufficiently similarly for our purposes.
9
+ object_is_any_of?(object, 'Enumerable', 'ActiveRecord::Relation')
10
+ end
11
+
12
+ # Wrap an Enumerable method which returns another collection
13
+ def self.exhibit_enum(*method_names, &post_process)
14
+ post_process ||= ->(result){exhibit(result)}
15
+ method_names.each do |method_name|
16
+ define_method(method_name) do |*args, &block|
17
+ result = __getobj__.public_send(method_name, *args, &block)
18
+ instance_exec(result, &post_process)
19
+ end
20
+ end
21
+ end
22
+ private_class_method :exhibit_enum
23
+
24
+ exhibit_query :[], :fetch, :slice, :values_at, :last
25
+ exhibit_enum :select, :grep, :reject, :to_enum, :sort, :sort_by, :reverse
26
+ exhibit_enum :partition do |result|
27
+ result.map{|group| exhibit(group)}
28
+ end
29
+ exhibit_enum :group_by do |result|
30
+ result.inject({}) { |h,(k,v)|
31
+ h.merge!(k => exhibit(v))
32
+ }
33
+ end
34
+
35
+ def each(*)
36
+ super do |e|
37
+ yield exhibit(e)
38
+ end
39
+ end
40
+
41
+ # `render '...', :collection => self` will call #to_ary on this
42
+ # before rendering, so we need to be prepared.
43
+ def to_ary
44
+ self
45
+ end
46
+
47
+ def render(template)
48
+ inject(ActiveSupport::SafeBuffer.new) { |output,element|
49
+ output << element.render(template)
50
+ }
51
+ end
52
+
53
+ end
@@ -0,0 +1,129 @@
1
+ require 'delegate'
2
+ require 'active_support/core_ext'
3
+
4
+ class Exhibit < SimpleDelegator
5
+ def self.exhibits
6
+ [
7
+ EnumerableExhibit,
8
+ BlogExhibit,
9
+ TextPostExhibit,
10
+ PicturePostExhibit,
11
+ LinkExhibit,
12
+ TagListExhibit
13
+ ]
14
+ end
15
+
16
+ def self.exhibit(object, context)
17
+ return object if exhibited_object?(object)
18
+ Rails.logger.debug "Exhibiting #{object.inspect}"
19
+ Rails.logger.debug "Exhibit context: #{context}"
20
+ object = Exhibited.new(object, context)
21
+ exhibits.inject(object) do |object, exhibit_class|
22
+ exhibit_class.exhibit_if_applicable(object, context)
23
+ end.tap do |obj|
24
+ Rails.logger.debug "Exhibits applied: #{obj.inspect_exhibits}"
25
+ end
26
+ end
27
+
28
+ def self.exhibit_if_applicable(object, context)
29
+ if applicable_to?(object)
30
+ new(object, context)
31
+ else
32
+ object
33
+ end
34
+ end
35
+
36
+ def self.applicable_to?(object)
37
+ false
38
+ end
39
+
40
+ def self.exhibited_object?(object)
41
+ object.respond_to?(:exhibited?) && object.exhibited?
42
+ end
43
+
44
+ def self.exhibit_query(*method_names)
45
+ method_names.each do |name|
46
+ define_method(name) do |*args, &block|
47
+ exhibit(super(*args, &block))
48
+ end
49
+ end
50
+ end
51
+ private_class_method :exhibit_query
52
+
53
+ # A helper for matching models to classes/modules, intended for use
54
+ # in .applicable_to?.
55
+ def self.object_is_any_of?(object, *classes)
56
+ # What with Rails development mode reloading making class matching
57
+ # unreliable, plus wanting to avoid adding dependencies to
58
+ # external class definitions if we can avoid it, we just match
59
+ # against class/module name strings rather than the actual class
60
+ # objects.
61
+
62
+ # Note that '&' is the set intersection operator for Arrays.
63
+ (classes.map(&:to_s) & object.class.ancestors.map(&:name)).any?
64
+ end
65
+ private_class_method :object_is_any_of?
66
+
67
+ attr_reader :context
68
+
69
+ def initialize(model, context)
70
+ @context = context
71
+ super(model)
72
+ end
73
+
74
+ alias_method :__class__, :class
75
+ def class
76
+ __getobj__.class
77
+ end
78
+
79
+ def exhibit(model)
80
+ Exhibit.exhibit(model, context)
81
+ end
82
+
83
+ def to_partial_path
84
+ if __getobj__.respond_to?(:to_partial_path)
85
+ __getobj__.to_partial_path
86
+ else
87
+ partialize_name(__getobj__.class.name)
88
+ end
89
+ end
90
+
91
+ def render(template)
92
+ template.render(:partial => to_partial_path, :object => self)
93
+ end
94
+
95
+ def exhibit_chain
96
+ inner_exhibits = defined?(super) ? super : []
97
+ [__class__] + inner_exhibits
98
+ end
99
+
100
+ def inspect_exhibits
101
+ exhibit_chain.map(&:to_s).join(':')
102
+ end
103
+
104
+ def inspect
105
+ "#{inspect_exhibits}(#{__getobj__.inspect})"
106
+ end
107
+
108
+ def exhibited?
109
+ true
110
+ end
111
+
112
+ private
113
+
114
+ # The terminator for the exhibit chain, and a marker that an object
115
+ # has been through the exhibit process
116
+ class Exhibited < Exhibit
117
+ def exhibit_chain
118
+ []
119
+ end
120
+
121
+ def to_model
122
+ __getobj__
123
+ end
124
+ end
125
+
126
+ def partialize_name(name)
127
+ "/#{name.underscore.pluralize}/#{name.demodulize.underscore}"
128
+ end
129
+ end
@@ -0,0 +1,5 @@
1
+ module ExhibitsHelper
2
+ def exhibit(model, context=self)
3
+ Exhibit.exhibit(model, context)
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: display_case
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Avdi Grimm
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-17 00:00:00.000000000Z
13
+ dependencies: []
14
+ description: An implementation of the Exhibit pattern, as described in Objects on
15
+ Rails
16
+ email:
17
+ - sam@codeodor.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - lib/display_case/enumerable_exhibit.rb
23
+ - lib/display_case/exhibit.rb
24
+ - lib/display_case/exhibits_helper.rb
25
+ - lib/display_case.rb
26
+ - LICENSE
27
+ - README.md
28
+ homepage: https://github.com/objects-on-rails/display-case
29
+ licenses: []
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubyforge_project:
48
+ rubygems_version: 1.8.8
49
+ signing_key:
50
+ specification_version: 3
51
+ summary: An implementation of the Exhibit pattern, as described in Objects on Rails
52
+ test_files: []