File: lib/radiant/resource_responses.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  module: Radiant#2
  module: ResourceResponses#3
has properties
module method: extended / 1 #4
method: responses #9
  module: InstanceMethods#15
has properties
method: response_for / 1 #16
method: wrap / 1 #37
  class: Collector#51
inherits from
  OpenStruct   
has properties
method: initialize #52
method: initialize_copy / 1 #57
  class: Response#65
inherits from
  Object ( Builtin-Module )
has properties
attribute: publish_formats [R] #66
attribute: publish_block [R] #66
attribute: blocks [R] #66
attribute: block_order [R] #66
method: initialize #67
method: initialize_copy / 1 #73
method: default / 1 #81
method: publish / 2 #88
method: each_published #97
method: each_format #103
method: method_missing / 3 #109

Code

   1  require 'ostruct'
   2  module Radiant
   3    module ResourceResponses
   4      def self.extended(base)
   5        base.send :class_inheritable_writer, :responses
   6        base.send :include, InstanceMethods
   7      end
   8      
   9      def responses
  10        r = (self.responses = read_inheritable_attribute(:responses) || Collector.new)
  11        yield r if block_given?
  12        r
  13      end
  14      
  15      module InstanceMethods
  16        def response_for(action)
  17          responses = self.class.responses.send(action)
  18          respond_to do |wants|
  19            responses.each_format do |f, format_block|
  20              if format_block
  21                wants.send(f, &wrap(format_block))
  22              else
  23                wants.send(f)
  24              end
  25            end
  26            responses.each_published do |pub, pub_block|
  27              wants.send(pub, &wrap(pub_block))
  28            end
  29            if responses.default
  30              wants.any(&wrap(responses.default))
  31            else
  32              wants.any
  33            end
  34          end
  35        end
  36        
  37        def wrap(proc)
  38          # Makes sure our response blocks get evaluated in the right context
  39          lambda do
  40            # Ruby 1.9.2 yields self in instance_eval... see https://gist.github.com/479572
  41            # lambdas are as strict as methods in 1.9.x, making sure that the args match, Procs are not.
  42            if RUBY_VERSION =~ /^1\.9/ and proc.lambda? and proc.arity != 1
  43              raise "You can only pass a proc ('Proc.new') or a lambda that takes exactly one arg (for self) to the wrap method."
  44            end
  45            
  46            instance_eval(&proc)
  47          end
  48        end
  49      end
  50      
  51      class Collector < OpenStruct
  52        def initialize
  53          super
  54          @table = Hash.new {|h,k| h[k] = Response.new }
  55        end
  56        
  57        def initialize_copy(orig)
  58          super
  59          @table.keys.each do |key|
  60            @table[key] = orig.send(key).dup
  61          end
  62        end
  63      end
  64      
  65      class Response
  66        attr_reader :publish_formats, :publish_block, :blocks, :block_order
  67        def initialize
  68          @publish_formats = []
  69          @blocks = {}
  70          @block_order = []
  71        end
  72        
  73        def initialize_copy(orig)
  74          @publish_formats = orig.publish_formats.dup
  75          @blocks = orig.blocks.dup
  76          @block_order = orig.block_order.dup
  77          @publish_block = orig.publish_block.dup if orig.publish_block
  78          @default = orig.default.dup if orig.default
  79        end
  80        
  81        def default(&block)
  82          if block_given?
  83            @default = block
  84          end
  85          @default
  86        end
  87        
  88        def publish(*formats, &block)
  89          @publish_formats.concat(formats)
  90          if block_given?
  91            @publish_block = block 
  92          else
  93            raise ArgumentError, "Block required to publish" unless @publish_block
  94          end
  95        end
  96        
  97        def each_published
  98          publish_formats.each do |format|
  99            yield format, publish_block if block_given?
 100          end
 101        end
 102 
 103        def each_format
 104          @block_order.each do |format|
 105            yield format, @blocks[format] if block_given?
 106          end
 107        end
 108 
 109        def method_missing(method, *args, &block)
 110          if block_given?
 111            @blocks[method] = block
 112            @block_order << method unless @block_order.include?(method)
 113          elsif args.empty?
 114            @block_order << method
 115          else
 116            super
 117          end
 118        end
 119      end
 120    end
 121  en