display_case 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -1,4 +1,73 @@
1
1
  display_case
2
2
  ============
3
3
 
4
- An implementation of the Exhibit pattern, as described in Objects on Rails
4
+ An implementation of the Exhibit pattern, as described in Objects on Rails
5
+
6
+ Description
7
+ -----------
8
+ If the Model is concerned with storing and manipulating business data, and the View is concerned with displaying it, you can think of the Exhibit as standing between them deciding which data to show, and in what order. It may also provide some extra presentation-specific information (such as the specific URLs for related resources) which the business model has no knowledge of by itself.
9
+
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 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
+
12
+ Technically, exhibit objects are a type of Decorator specialized for presenting models to an end user.
13
+
14
+ For the purposes of clarity, here's a rundown of the essential characteristics of an Exhibit object.
15
+
16
+ An Exhibit object:
17
+
18
+ 1. **Wraps a single model instance.**
19
+ 1. **Is a true Decorator.** All unrecognized messages are passed through to the underlying object. This facilitates a gradual migration to the use of Exhibits to encapsulate presentation knowledge, since they can be layered onto models without any change to the existing views. It also enables multiple Exhibits to be layered onto an object, each handling different aspects of presentation.
20
+ 1. **Brings together a model and a context.** Exhibits need a reference to a "context" object—either a controller or a view context—in order to be able to render templates as well as construct URLs for the object or related resources.
21
+ 1. **Encapsulates decisions about how to render an object.** The tell-tale of an Exhibit is telling an object "render yourself", rather than explicitly rendering a template and passing the object in as an argument.
22
+ 1. **May modify the behavior of an object.** For instance, an Exhibit might impose a scope on a `Blog#entries` association which only returns entries that are visible to the current user (as determined from the Exhibit's controller context). Or it might reformat the return value of a `#social_security_number` method to include dashes and have all but the last four digits obscured: `***-**-5678`.
23
+
24
+ Installation
25
+ ------------
26
+ `gem 'display_case'` in your Gemfile if you're using Bundler, or `gem install display_case` from the command line.
27
+
28
+ Usage
29
+ -----
30
+ Your exhibits will look something like this:
31
+ ``` ruby
32
+ # app/exhibits/league_exhibit.rb
33
+
34
+ class LeagueExhibit < Exhibit
35
+ def self.applicable_to?(object)
36
+ object.class.name == 'League'
37
+ end
38
+
39
+ def render_icon(template)
40
+ template.render(partial: 'leagues/icon', locals: {league: self})
41
+ end
42
+ end
43
+ ```
44
+
45
+ Then in your controller, where you're instantiating a League, wrap it in a call to the `exhibit` helper to turn get the Exhibited object, rather than the raw one.
46
+ ``` ruby
47
+ # app/controllers/leagues_controller.rb
48
+ class LeaguesController < ApplicationController
49
+ # ...
50
+ def index
51
+ # display_case automatically wraps the individual objects contained in
52
+ # an Enumerable or ActiveRecord::Relation collections
53
+ @leagues = exhibit(League.all)
54
+ end
55
+
56
+ def show
57
+ # of course it will also wrap your individual objects
58
+ @league = exhibit(League.find(params[:id]))
59
+ end
60
+ end
61
+ ```
62
+
63
+ Finally, in your view, you can use your Exhibit:
64
+ ```
65
+ <!-- app/views/leagues/index.html.erb -->
66
+ <% @leagues.each do |league| %>
67
+ <%= league.render_icon(self) %> <!-- self is this "template", the parameter to the method we defined in LeagueExhibit -->
68
+ <% end %>
69
+ ```
70
+
71
+ Configuration
72
+ -------------
73
+ Because Rails lazily-loads files, in development mode DisplayCase will search /app/exhibits to load the Exhibits found there. If your Exhibits are elsewhere, you can set `DisplayCase.definition_file_paths = ['list/of/directories', 'to/find/exhibits']` in your config/environments/development.rb.
@@ -1,20 +1,21 @@
1
1
  require 'delegate'
2
2
  require 'active_support/core_ext'
3
+ require 'display_case/railtie' if defined?(Rails)
3
4
 
4
5
  class Exhibit < SimpleDelegator
6
+ @@exhibits = []
7
+
5
8
  def self.exhibits
6
- [
7
- EnumerableExhibit,
8
- BlogExhibit,
9
- TextPostExhibit,
10
- PicturePostExhibit,
11
- LinkExhibit,
12
- TagListExhibit
13
- ]
9
+ @@exhibits
10
+ end
11
+
12
+ def self.inherited(child)
13
+ @@exhibits << child
14
14
  end
15
15
 
16
16
  def self.exhibit(object, context)
17
17
  return object if exhibited_object?(object)
18
+ Rails.logger.debug "Registered exhibits: #{@@exhibits}"
18
19
  Rails.logger.debug "Exhibiting #{object.inspect}"
19
20
  Rails.logger.debug "Exhibit context: #{context}"
20
21
  object = Exhibited.new(object, context)
@@ -0,0 +1,24 @@
1
+ module DisplayCase
2
+ class << self
3
+ # An Array of strings specifying locations that should be searched for
4
+ # exhibit classes and definitions. By default, "/app/exhibits" will be searched and
5
+ # existing file will be loaded.
6
+ attr_accessor :definition_file_paths
7
+ end
8
+
9
+ self.definition_file_paths = %w(app/exhibits)
10
+
11
+ def self.find_definitions
12
+ absolute_definition_file_paths = definition_file_paths.map {|path| File.expand_path(path) }
13
+
14
+ absolute_definition_file_paths.uniq.each do |path|
15
+ load("#{path}.rb") if File.exists?("#{path}.rb")
16
+
17
+ if File.directory? path
18
+ Dir[File.join(path, '**', '*.rb')].sort.each do |file|
19
+ load file
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,7 @@
1
+ module DisplayCase
2
+ class Railtie < Rails::Railtie
3
+ config.to_prepare do
4
+ DisplayCase.find_definitions if Rails.env.development?
5
+ end
6
+ end
7
+ end
data/lib/display_case.rb CHANGED
@@ -0,0 +1,5 @@
1
+ require_relative 'display_case/exhibit'
2
+ require_relative 'display_case/enumerable_exhibit'
3
+ require_relative 'display_case/exhibits_helper'
4
+ require_relative 'display_case/find_definitions'
5
+
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.0
4
+ version: 0.0.1
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: 2012-05-17 00:00:00.000000000Z
12
+ date: 2012-05-23 00:00:00.000000000Z
13
13
  dependencies: []
14
14
  description: An implementation of the Exhibit pattern, as described in Objects on
15
15
  Rails
@@ -22,6 +22,8 @@ files:
22
22
  - lib/display_case/enumerable_exhibit.rb
23
23
  - lib/display_case/exhibit.rb
24
24
  - lib/display_case/exhibits_helper.rb
25
+ - lib/display_case/find_definitions.rb
26
+ - lib/display_case/railtie.rb
25
27
  - lib/display_case.rb
26
28
  - LICENSE
27
29
  - README.md