racket-mvc 0.4.0 → 0.5.0
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.
- checksums.yaml +4 -4
 - data/README.md +7 -5
 - data/lib/racket.rb +25 -7
 - data/lib/racket/application.rb +70 -136
 - data/lib/racket/controller.rb +95 -38
 - data/lib/racket/current.rb +1 -1
 - data/lib/racket/helpers/file.rb +7 -5
 - data/lib/racket/helpers/routing.rb +5 -5
 - data/lib/racket/helpers/sass.rb +11 -11
 - data/lib/racket/helpers/view.rb +8 -5
 - data/lib/racket/plugins/base.rb +1 -1
 - data/lib/racket/plugins/sass.rb +1 -1
 - data/lib/racket/request.rb +3 -3
 - data/lib/racket/response.rb +1 -1
 - data/lib/racket/router.rb +31 -12
 - data/lib/racket/session.rb +3 -3
 - data/lib/racket/settings/application.rb +27 -33
 - data/lib/racket/settings/base.rb +19 -8
 - data/lib/racket/settings/controller.rb +9 -7
 - data/lib/racket/settings/defaults.rb +81 -0
 - data/lib/racket/utils.rb +19 -15
 - data/lib/racket/utils/application.rb +4 -114
 - data/lib/racket/utils/application/handler_stack.rb +163 -0
 - data/lib/racket/utils/application/logger.rb +72 -0
 - data/lib/racket/utils/application/registry_builder.rb +88 -0
 - data/lib/racket/utils/application/stateless_services.rb +73 -0
 - data/lib/racket/utils/exceptions.rb +3 -3
 - data/lib/racket/utils/file_system.rb +75 -47
 - data/lib/racket/utils/helpers.rb +35 -13
 - data/lib/racket/utils/routing.rb +62 -46
 - data/lib/racket/utils/views.rb +19 -187
 - data/lib/racket/utils/views/renderer.rb +75 -0
 - data/lib/racket/utils/views/template_cache.rb +126 -0
 - data/lib/racket/utils/views/template_locator.rb +83 -0
 - data/lib/racket/utils/views/template_resolver.rb +112 -0
 - data/lib/racket/version.rb +2 -2
 - data/lib/racket/view_manager.rb +12 -4
 - data/rake/utils.rb +5 -5
 - data/spec/_custom.rb +69 -19
 - data/spec/_default.rb +60 -44
 - data/spec/_plugin.rb +12 -14
 - data/spec/_template_cache.rb +176 -0
 - data/spec/racket.rb +10 -13
 - data/spec/test_custom_app/controllers/sub1/custom_sub_controller_1.rb +1 -1
 - data/spec/test_custom_app/controllers/sub3/custom_sub_controller_3.rb +19 -1
 - data/spec/test_custom_app/controllers/sub5/custom_sub_controller_5.rb +8 -0
 - data/spec/test_custom_app/files/stuff.rb +3 -0
 - data/spec/test_custom_app/files/triplet.erb +5 -0
 - data/spec/test_custom_app/templates/sub5/text.erb +3 -0
 - data/spec/test_default_app/controllers/default_root_controller.rb +3 -0
 - data/spec/test_default_app/controllers/sub1/default_sub_controller_1.rb +1 -1
 - metadata +52 -11
 
    
        data/lib/racket/utils/helpers.rb
    CHANGED
    
    | 
         @@ -1,5 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # Racket - The noisy Rack MVC framework
         
     | 
| 
       2 
     | 
    
         
            -
            # Copyright (C) 2015  Lars Olsson <lasso@lassoweb.se>
         
     | 
| 
      
 2 
     | 
    
         
            +
            # Copyright (C) 2015-2016  Lars Olsson <lasso@lassoweb.se>
         
     | 
| 
       3 
3 
     | 
    
         
             
            #
         
     | 
| 
       4 
4 
     | 
    
         
             
            # This file is part of Racket.
         
     | 
| 
       5 
5 
     | 
    
         
             
            #
         
     | 
| 
         @@ -22,9 +22,25 @@ module Racket 
     | 
|
| 
       22 
22 
     | 
    
         
             
                module Helpers
         
     | 
| 
       23 
23 
     | 
    
         
             
                  # Cache for helpers, ensuring that helpers get loaded exactly once.
         
     | 
| 
       24 
24 
     | 
    
         
             
                  class HelperCache
         
     | 
| 
       25 
     | 
    
         
            -
                     
     | 
| 
      
 25 
     | 
    
         
            +
                    # Returns a service proc that can be used by the registry.
         
     | 
| 
      
 26 
     | 
    
         
            +
                    #
         
     | 
| 
      
 27 
     | 
    
         
            +
                    # @param  [Hash] _options (unused)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    # @return [Proc]
         
     | 
| 
      
 29 
     | 
    
         
            +
                    def self.service(_options = {})
         
     | 
| 
      
 30 
     | 
    
         
            +
                      lambda do |reg|
         
     | 
| 
      
 31 
     | 
    
         
            +
                        new(
         
     | 
| 
      
 32 
     | 
    
         
            +
                          reg.application_settings.helper_dir,
         
     | 
| 
      
 33 
     | 
    
         
            +
                          reg.application_logger,
         
     | 
| 
      
 34 
     | 
    
         
            +
                          reg.utils
         
     | 
| 
      
 35 
     | 
    
         
            +
                        )
         
     | 
| 
      
 36 
     | 
    
         
            +
                      end
         
     | 
| 
      
 37 
     | 
    
         
            +
                    end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                    def initialize(helper_dir, logger, utils)
         
     | 
| 
       26 
40 
     | 
    
         
             
                      @helper_dir = helper_dir
         
     | 
| 
       27 
41 
     | 
    
         
             
                      @helpers = {}
         
     | 
| 
      
 42 
     | 
    
         
            +
                      @logger = logger
         
     | 
| 
      
 43 
     | 
    
         
            +
                      @utils = utils
         
     | 
| 
       28 
44 
     | 
    
         
             
                    end
         
     | 
| 
       29 
45 
     | 
    
         | 
| 
       30 
46 
     | 
    
         
             
                    # Loads helper files and return the loadad modules as a hash. Any helper files that
         
     | 
| 
         @@ -51,20 +67,24 @@ module Racket 
     | 
|
| 
       51 
67 
     | 
    
         | 
| 
       52 
68 
     | 
    
         
             
                    def load_helper_file(helper)
         
     | 
| 
       53 
69 
     | 
    
         
             
                      require_helper_file(helper)
         
     | 
| 
       54 
     | 
    
         
            -
                       
     | 
| 
      
 70 
     | 
    
         
            +
                      load_helper_module(helper)
         
     | 
| 
       55 
71 
     | 
    
         
             
                    end
         
     | 
| 
       56 
72 
     | 
    
         | 
| 
       57 
73 
     | 
    
         
             
                    def require_helper_file(helper)
         
     | 
| 
       58 
     | 
    
         
            -
                      loaded =  
     | 
| 
       59 
     | 
    
         
            -
                       
     | 
| 
      
 74 
     | 
    
         
            +
                      loaded = @utils.safe_require("racket/helpers/#{helper}")
         
     | 
| 
      
 75 
     | 
    
         
            +
                      @utils.safe_require(@utils.build_path(@helper_dir, helper).to_s) if !loaded && @helper_dir
         
     | 
| 
       60 
76 
     | 
    
         
             
                    end
         
     | 
| 
       61 
77 
     | 
    
         | 
| 
       62 
     | 
    
         
            -
                     
     | 
| 
      
 78 
     | 
    
         
            +
                    # Loads a helper module
         
     | 
| 
      
 79 
     | 
    
         
            +
                    #
         
     | 
| 
      
 80 
     | 
    
         
            +
                    # @param [Symbol] helper
         
     | 
| 
      
 81 
     | 
    
         
            +
                    # @return [Module]
         
     | 
| 
      
 82 
     | 
    
         
            +
                    def load_helper_module(helper)
         
     | 
| 
       63 
83 
     | 
    
         
             
                      helper_module = nil
         
     | 
| 
       64 
     | 
    
         
            -
                       
     | 
| 
      
 84 
     | 
    
         
            +
                      @utils.run_block(NameError) do
         
     | 
| 
       65 
85 
     | 
    
         
             
                        helper_module =
         
     | 
| 
       66 
86 
     | 
    
         
             
                          Racket::Helpers.const_get(helper.to_s.split('_').collect(&:capitalize).join.to_sym)
         
     | 
| 
       67 
     | 
    
         
            -
                         
     | 
| 
      
 87 
     | 
    
         
            +
                        @logger.inform_dev("Loaded helper module #{helper.inspect}.")
         
     | 
| 
       68 
88 
     | 
    
         
             
                      end
         
     | 
| 
       69 
89 
     | 
    
         
             
                      helper_module
         
     | 
| 
       70 
90 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -73,23 +93,25 @@ module Racket 
     | 
|
| 
       73 
93 
     | 
    
         
             
                  # Applies helpers to a controller class by including the modules in the class.
         
     | 
| 
       74 
94 
     | 
    
         
             
                  #
         
     | 
| 
       75 
95 
     | 
    
         
             
                  # @param [Class] klass
         
     | 
| 
       76 
     | 
    
         
            -
                  def  
     | 
| 
      
 96 
     | 
    
         
            +
                  def apply_helpers(klass)
         
     | 
| 
       77 
97 
     | 
    
         
             
                    klass.helper unless klass.settings.fetch(:helpers) # Makes sure default helpers are loaded.
         
     | 
| 
       78 
98 
     | 
    
         
             
                    __apply_helpers(klass)
         
     | 
| 
       79 
99 
     | 
    
         
             
                    nil
         
     | 
| 
       80 
100 
     | 
    
         
             
                  end
         
     | 
| 
       81 
101 
     | 
    
         | 
| 
       82 
     | 
    
         
            -
                   
     | 
| 
      
 102 
     | 
    
         
            +
                  # Applies helpers to a controller class by including the modules in the class.
         
     | 
| 
      
 103 
     | 
    
         
            +
                  #
         
     | 
| 
      
 104 
     | 
    
         
            +
                  # @param [Class] klass
         
     | 
| 
      
 105 
     | 
    
         
            +
                  # @return [Class]
         
     | 
| 
      
 106 
     | 
    
         
            +
                  def __apply_helpers(klass)
         
     | 
| 
       83 
107 
     | 
    
         
             
                    klass.settings.fetch(:helpers).reverse_each do |pair|
         
     | 
| 
       84 
108 
     | 
    
         
             
                      helper_key, helper = pair
         
     | 
| 
       85 
     | 
    
         
            -
                       
     | 
| 
      
 109 
     | 
    
         
            +
                      klass.context.logger.inform_dev(
         
     | 
| 
       86 
110 
     | 
    
         
             
                        "Adding helper module #{helper_key.inspect} to #{klass}"
         
     | 
| 
       87 
111 
     | 
    
         
             
                      )
         
     | 
| 
       88 
112 
     | 
    
         
             
                      klass.send(:include, helper)
         
     | 
| 
       89 
113 
     | 
    
         
             
                    end
         
     | 
| 
       90 
114 
     | 
    
         
             
                  end
         
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
                  private_class_method :__apply_helpers
         
     | 
| 
       93 
115 
     | 
    
         
             
                end
         
     | 
| 
       94 
116 
     | 
    
         
             
              end
         
     | 
| 
       95 
117 
     | 
    
         
             
            end
         
     | 
    
        data/lib/racket/utils/routing.rb
    CHANGED
    
    | 
         @@ -1,5 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # Racket - The noisy Rack MVC framework
         
     | 
| 
       2 
     | 
    
         
            -
            # Copyright (C) 2015  Lars Olsson <lasso@lassoweb.se>
         
     | 
| 
      
 2 
     | 
    
         
            +
            # Copyright (C) 2015-2016  Lars Olsson <lasso@lassoweb.se>
         
     | 
| 
       3 
3 
     | 
    
         
             
            #
         
     | 
| 
       4 
4 
     | 
    
         
             
            # This file is part of Racket.
         
     | 
| 
       5 
5 
     | 
    
         
             
            #
         
     | 
| 
         @@ -25,10 +25,19 @@ module Racket 
     | 
|
| 
       25 
25 
     | 
    
         | 
| 
       26 
26 
     | 
    
         
             
                  # Class for caching actions
         
     | 
| 
       27 
27 
     | 
    
         
             
                  class ActionCache
         
     | 
| 
      
 28 
     | 
    
         
            +
                    # Returns a service proc that can be used by the registry.
         
     | 
| 
      
 29 
     | 
    
         
            +
                    #
         
     | 
| 
      
 30 
     | 
    
         
            +
                    # @param  [Hash] _options (unused)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    # @return [Proc]
         
     | 
| 
      
 32 
     | 
    
         
            +
                    def self.service(_options = {})
         
     | 
| 
      
 33 
     | 
    
         
            +
                      ->(reg) { new(reg.application_logger) }
         
     | 
| 
      
 34 
     | 
    
         
            +
                    end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
       28 
36 
     | 
    
         
             
                    attr_reader :items
         
     | 
| 
       29 
37 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
                    def initialize
         
     | 
| 
      
 38 
     | 
    
         
            +
                    def initialize(logger)
         
     | 
| 
       31 
39 
     | 
    
         
             
                      @items = {}
         
     | 
| 
      
 40 
     | 
    
         
            +
                      @logger = logger
         
     | 
| 
       32 
41 
     | 
    
         
             
                    end
         
     | 
| 
       33 
42 
     | 
    
         | 
| 
       34 
43 
     | 
    
         
             
                    # Returns whether +controller_class+ is in the cache and that it contains the action
         
     | 
| 
         @@ -50,7 +59,7 @@ module Racket 
     | 
|
| 
       50 
59 
     | 
    
         
             
                      __add(controller_class)
         
     | 
| 
       51 
60 
     | 
    
         
             
                      actions = @items[controller_class].to_a
         
     | 
| 
       52 
61 
     | 
    
         
             
                      @items[controller_class] = actions
         
     | 
| 
       53 
     | 
    
         
            -
                       
     | 
| 
      
 62 
     | 
    
         
            +
                      @logger.inform_dev(
         
     | 
| 
       54 
63 
     | 
    
         
             
                        "Registering actions #{actions} for #{controller_class}."
         
     | 
| 
       55 
64 
     | 
    
         
             
                      ) && nil
         
     | 
| 
       56 
65 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -69,55 +78,62 @@ module Racket 
     | 
|
| 
       69 
78 
     | 
    
         
             
                    end
         
     | 
| 
       70 
79 
     | 
    
         
             
                  end
         
     | 
| 
       71 
80 
     | 
    
         | 
| 
       72 
     | 
    
         
            -
                  #  
     | 
| 
       73 
     | 
    
         
            -
                   
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
     | 
    
         
            -
             
     | 
| 
       77 
     | 
    
         
            -
                     
     | 
| 
       78 
     | 
    
         
            -
                     
     | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
             
     | 
| 
      
 81 
     | 
    
         
            +
                  # Class responsible for dispatching requests to controllers.
         
     | 
| 
      
 82 
     | 
    
         
            +
                  class Dispatcher
         
     | 
| 
      
 83 
     | 
    
         
            +
                    # Extracts the target class, target params and target action from a list of valid routes.
         
     | 
| 
      
 84 
     | 
    
         
            +
                    #
         
     | 
| 
      
 85 
     | 
    
         
            +
                    # @param [HttpRouter::Response] response
         
     | 
| 
      
 86 
     | 
    
         
            +
                    # @return [Array]
         
     | 
| 
      
 87 
     | 
    
         
            +
                    def self.extract_target(response)
         
     | 
| 
      
 88 
     | 
    
         
            +
                      target_klass = response.route.dest
         
     | 
| 
      
 89 
     | 
    
         
            +
                      params = response.param_values.first.reject(&:empty?)
         
     | 
| 
      
 90 
     | 
    
         
            +
                      action =
         
     | 
| 
      
 91 
     | 
    
         
            +
                        if params.empty?
         
     | 
| 
      
 92 
     | 
    
         
            +
                          target_klass.settings.fetch(:default_action)
         
     | 
| 
      
 93 
     | 
    
         
            +
                        else
         
     | 
| 
      
 94 
     | 
    
         
            +
                          params.shift.to_sym
         
     | 
| 
      
 95 
     | 
    
         
            +
                        end
         
     | 
| 
      
 96 
     | 
    
         
            +
                      [target_klass, params, action]
         
     | 
| 
      
 97 
     | 
    
         
            +
                    end
         
     | 
| 
       82 
98 
     | 
    
         | 
| 
       83 
     | 
    
         
            -
             
     | 
| 
       84 
     | 
    
         
            -
                     
     | 
| 
       85 
     | 
    
         
            -
                     
     | 
| 
       86 
     | 
    
         
            -
                     
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
      
 99 
     | 
    
         
            +
                    # Constructor
         
     | 
| 
      
 100 
     | 
    
         
            +
                    #
         
     | 
| 
      
 101 
     | 
    
         
            +
                    # @param [Hash] env
         
     | 
| 
      
 102 
     | 
    
         
            +
                    # @param [Array] target_info
         
     | 
| 
      
 103 
     | 
    
         
            +
                    def initialize(env, target_info)
         
     | 
| 
      
 104 
     | 
    
         
            +
                      @env = env
         
     | 
| 
      
 105 
     | 
    
         
            +
                      @controller_class, @params, @action = target_info
         
     | 
| 
      
 106 
     | 
    
         
            +
                    end
         
     | 
| 
       88 
107 
     | 
    
         | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
       94 
     | 
    
         
            -
             
     | 
| 
       95 
     | 
    
         
            -
             
     | 
| 
       96 
     | 
    
         
            -
                    controller_class, params, action = target_info
         
     | 
| 
      
 108 
     | 
    
         
            +
                    # Dispatches request to a controller. This is the default action whenever a matching
         
     | 
| 
      
 109 
     | 
    
         
            +
                    # route for a request is found.
         
     | 
| 
      
 110 
     | 
    
         
            +
                    #
         
     | 
| 
      
 111 
     | 
    
         
            +
                    # @return [Array] A racket response triplet
         
     | 
| 
      
 112 
     | 
    
         
            +
                    def dispatch
         
     | 
| 
      
 113 
     | 
    
         
            +
                      # Rewrite PATH_INFO to reflect that we split out the parameters
         
     | 
| 
      
 114 
     | 
    
         
            +
                      update_path_info(@params.length)
         
     | 
| 
       97 
115 
     | 
    
         | 
| 
       98 
     | 
    
         
            -
             
     | 
| 
       99 
     | 
    
         
            -
             
     | 
| 
      
 116 
     | 
    
         
            +
                      # Call controller
         
     | 
| 
      
 117 
     | 
    
         
            +
                      call_controller(Current.init(RouterParams.new(@action, @params, @env)))
         
     | 
| 
      
 118 
     | 
    
         
            +
                    end
         
     | 
| 
       100 
119 
     | 
    
         | 
| 
       101 
     | 
    
         
            -
                     
     | 
| 
       102 
     | 
    
         
            -
                    call_controller(
         
     | 
| 
       103 
     | 
    
         
            -
                      controller_class,
         
     | 
| 
       104 
     | 
    
         
            -
                      Current.init(RouterParams.new(action, params, env))
         
     | 
| 
       105 
     | 
    
         
            -
                    )
         
     | 
| 
       106 
     | 
    
         
            -
                  end
         
     | 
| 
      
 120 
     | 
    
         
            +
                    private
         
     | 
| 
       107 
121 
     | 
    
         | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
       110 
     | 
    
         
            -
             
     | 
| 
       111 
     | 
    
         
            -
                  # @param [Fixnum] num_params
         
     | 
| 
       112 
     | 
    
         
            -
                  # @return [nil]
         
     | 
| 
       113 
     | 
    
         
            -
                  def self.update_path_info(env, num_params)
         
     | 
| 
       114 
     | 
    
         
            -
                    env['PATH_INFO'] = env['PATH_INFO']
         
     | 
| 
       115 
     | 
    
         
            -
                                       .split('/')[0...-num_params]
         
     | 
| 
       116 
     | 
    
         
            -
                                       .join('/') unless num_params.zero?
         
     | 
| 
       117 
     | 
    
         
            -
                    nil
         
     | 
| 
       118 
     | 
    
         
            -
                  end
         
     | 
| 
      
 122 
     | 
    
         
            +
                    def call_controller(mod)
         
     | 
| 
      
 123 
     | 
    
         
            +
                      @controller_class.new.extend(mod).__run
         
     | 
| 
      
 124 
     | 
    
         
            +
                    end
         
     | 
| 
       119 
125 
     | 
    
         | 
| 
       120 
     | 
    
         
            -
             
     | 
| 
      
 126 
     | 
    
         
            +
                    # Updates the PATH_INFO environment variable.
         
     | 
| 
      
 127 
     | 
    
         
            +
                    #
         
     | 
| 
      
 128 
     | 
    
         
            +
                    # @param [Fixnum] num_params
         
     | 
| 
      
 129 
     | 
    
         
            +
                    # @return [nil]
         
     | 
| 
      
 130 
     | 
    
         
            +
                    def update_path_info(num_params)
         
     | 
| 
      
 131 
     | 
    
         
            +
                      @env['PATH_INFO'] = @env['PATH_INFO']
         
     | 
| 
      
 132 
     | 
    
         
            +
                                          .split('/')[0...-num_params]
         
     | 
| 
      
 133 
     | 
    
         
            +
                                          .join('/') unless num_params.zero?
         
     | 
| 
      
 134 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 135 
     | 
    
         
            +
                    end
         
     | 
| 
      
 136 
     | 
    
         
            +
                  end
         
     | 
| 
       121 
137 
     | 
    
         
             
                end
         
     | 
| 
       122 
138 
     | 
    
         
             
              end
         
     | 
| 
       123 
139 
     | 
    
         
             
            end
         
     | 
    
        data/lib/racket/utils/views.rb
    CHANGED
    
    | 
         @@ -1,5 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # Racket - The noisy Rack MVC framework
         
     | 
| 
       2 
     | 
    
         
            -
            # Copyright (C) 2015  Lars Olsson <lasso@lassoweb.se>
         
     | 
| 
      
 2 
     | 
    
         
            +
            # Copyright (C) 2015-2016  Lars Olsson <lasso@lassoweb.se>
         
     | 
| 
       3 
3 
     | 
    
         
             
            #
         
     | 
| 
       4 
4 
     | 
    
         
             
            # This file is part of Racket.
         
     | 
| 
       5 
5 
     | 
    
         
             
            #
         
     | 
| 
         @@ -18,197 +18,29 @@ 
     | 
|
| 
       18 
18 
     | 
    
         | 
| 
       19 
19 
     | 
    
         
             
            require 'tilt'
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
      
 21 
     | 
    
         
            +
            require_relative 'views/renderer.rb'
         
     | 
| 
      
 22 
     | 
    
         
            +
            require_relative 'views/template_cache.rb'
         
     | 
| 
      
 23 
     | 
    
         
            +
            require_relative 'views/template_locator.rb'
         
     | 
| 
      
 24 
     | 
    
         
            +
            require_relative 'views/template_resolver.rb'
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
       21 
26 
     | 
    
         
             
            module Racket
         
     | 
| 
       22 
27 
     | 
    
         
             
              module Utils
         
     | 
| 
       23 
     | 
    
         
            -
                #  
     | 
| 
      
 28 
     | 
    
         
            +
                # Namespace for view utilities
         
     | 
| 
       24 
29 
     | 
    
         
             
                module Views
         
     | 
| 
       25 
     | 
    
         
            -
                  #  
     | 
| 
       26 
     | 
    
         
            -
                   
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
                     
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
                     
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
                     
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
                    def ensure_in_cache(path, template_params)
         
     | 
| 
       38 
     | 
    
         
            -
                      return @cache[path] if @cache.key?(path)
         
     | 
| 
       39 
     | 
    
         
            -
                      @cache[path] = TemplateLocator.calculate_path(path, template_params)
         
     | 
| 
       40 
     | 
    
         
            -
                    end
         
     | 
| 
       41 
     | 
    
         
            -
                  end
         
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
                  # Class used for locating templates.
         
     | 
| 
       44 
     | 
    
         
            -
                  class TemplateLocator
         
     | 
| 
       45 
     | 
    
         
            -
                    def initialize(layout_base_dir, view_base_dir)
         
     | 
| 
       46 
     | 
    
         
            -
                      @layout_base_dir = layout_base_dir
         
     | 
| 
       47 
     | 
    
         
            -
                      @view_base_dir = view_base_dir
         
     | 
| 
       48 
     | 
    
         
            -
                      @layout_cache = TemplateCache.new
         
     | 
| 
       49 
     | 
    
         
            -
                      @view_cache = TemplateCache.new
         
     | 
| 
       50 
     | 
    
         
            -
                    end
         
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
                    # Returns the layout associated with the current request. On the first request to any action
         
     | 
| 
       53 
     | 
    
         
            -
                    # the result is cached, meaning that the layout only needs to be looked up once.
         
     | 
| 
       54 
     | 
    
         
            -
                    #
         
     | 
| 
       55 
     | 
    
         
            -
                    # @param [Racket::Controller] controller
         
     | 
| 
       56 
     | 
    
         
            -
                    # @return [String|nil]
         
     | 
| 
       57 
     | 
    
         
            -
                    def get_layout(controller)
         
     | 
| 
       58 
     | 
    
         
            -
                      get_template(TemplateParams.new(:layout, controller, @layout_base_dir, @layout_cache))
         
     | 
| 
       59 
     | 
    
         
            -
                    end
         
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
                    # Returns the view associated with the current request. On the first request to any action
         
     | 
| 
       62 
     | 
    
         
            -
                    # the result is cached, meaning that the view only needs to be looked up once.
         
     | 
| 
       63 
     | 
    
         
            -
                    #
         
     | 
| 
       64 
     | 
    
         
            -
                    # @param [Racket::Controller] controller
         
     | 
| 
       65 
     | 
    
         
            -
                    # @return [String|nil]
         
     | 
| 
       66 
     | 
    
         
            -
                    def get_view(controller)
         
     | 
| 
       67 
     | 
    
         
            -
                      get_template(TemplateParams.new(:view, controller, @view_base_dir, @view_cache))
         
     | 
| 
       68 
     | 
    
         
            -
                    end
         
     | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
       70 
     | 
    
         
            -
                    private
         
     | 
| 
       71 
     | 
    
         
            -
             
     | 
| 
       72 
     | 
    
         
            -
                    # Tries to locate a template matching +path+ in the file system and returns the path if a
         
     | 
| 
       73 
     | 
    
         
            -
                    # matching file is found. If no matching file is found, +nil+ is returned. The result is
         
     | 
| 
       74 
     | 
    
         
            -
                    # cached, meaning that the filesystem lookup for a specific path will only happen once.
         
     | 
| 
       75 
     | 
    
         
            -
                    #
         
     | 
| 
       76 
     | 
    
         
            -
                    # @param [TemplateParams] template_params
         
     | 
| 
       77 
     | 
    
         
            -
                    # @return [String|nil]
         
     | 
| 
       78 
     | 
    
         
            -
                    def get_template(template_params)
         
     | 
| 
       79 
     | 
    
         
            -
                      klass = self.class
         
     | 
| 
       80 
     | 
    
         
            -
                      path = klass.get_template_path(template_params.controller)
         
     | 
| 
       81 
     | 
    
         
            -
                      template = template_params.cache.ensure_in_cache(path, template_params)
         
     | 
| 
       82 
     | 
    
         
            -
                      klass.resolve_template(path, template, template_params)
         
     | 
| 
       83 
     | 
    
         
            -
                    end
         
     | 
| 
       84 
     | 
    
         
            -
             
     | 
| 
       85 
     | 
    
         
            -
                    def self.calculate_path(path, template_params)
         
     | 
| 
       86 
     | 
    
         
            -
                      type, controller, base_dir = template_params.to_a
         
     | 
| 
       87 
     | 
    
         
            -
                      default_template = controller.settings.fetch("default_#{type}".to_sym)
         
     | 
| 
       88 
     | 
    
         
            -
                      template =
         
     | 
| 
       89 
     | 
    
         
            -
                        TemplateLocator.lookup_template_with_default(
         
     | 
| 
       90 
     | 
    
         
            -
                          Utils.fs_path(base_dir, path), default_template
         
     | 
| 
       91 
     | 
    
         
            -
                        )
         
     | 
| 
       92 
     | 
    
         
            -
                      ::Racket::Application.inform_dev(
         
     | 
| 
       93 
     | 
    
         
            -
                        "Using #{type} #{template.inspect} for #{controller.class}.#{controller.racket.action}."
         
     | 
| 
       94 
     | 
    
         
            -
                      )
         
     | 
| 
       95 
     | 
    
         
            -
                      template
         
     | 
| 
       96 
     | 
    
         
            -
                    end
         
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
     | 
    
         
            -
                    def self.resolve_template(path, template, template_params)
         
     | 
| 
       99 
     | 
    
         
            -
                      return template unless template.is_a?(Proc)
         
     | 
| 
       100 
     | 
    
         
            -
                      _, controller, base_dir = template_params.to_a
         
     | 
| 
       101 
     | 
    
         
            -
                      lookup_template(
         
     | 
| 
       102 
     | 
    
         
            -
                        Utils.fs_path(
         
     | 
| 
       103 
     | 
    
         
            -
                          Utils.fs_path(base_dir, path).dirname,
         
     | 
| 
       104 
     | 
    
         
            -
                          call_template_proc(template, controller)
         
     | 
| 
       105 
     | 
    
         
            -
                        )
         
     | 
| 
       106 
     | 
    
         
            -
                      )
         
     | 
| 
       107 
     | 
    
         
            -
                    end
         
     | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
       109 
     | 
    
         
            -
                    # Calls a template proc. Depending on how many parameters the template proc takes, different
         
     | 
| 
       110 
     | 
    
         
            -
                    # types of information will be passed to the proc.
         
     | 
| 
       111 
     | 
    
         
            -
                    # If the proc takes zero parameters, no information will be passed.
         
     | 
| 
       112 
     | 
    
         
            -
                    # If the proc takes one parameter, it will contain the current action.
         
     | 
| 
       113 
     | 
    
         
            -
                    # If the proc takes two parameters, they will contain the current action and the current
         
     | 
| 
       114 
     | 
    
         
            -
                    #   params.
         
     | 
| 
       115 
     | 
    
         
            -
                    # If the proc takes three parameters, they will contain the current action, the current
         
     | 
| 
       116 
     | 
    
         
            -
                    # params and the current request.
         
     | 
| 
       117 
     | 
    
         
            -
                    #
         
     | 
| 
       118 
     | 
    
         
            -
                    # @param [Proc] proc
         
     | 
| 
       119 
     | 
    
         
            -
                    # @param [Racket::Controller] controller
         
     | 
| 
       120 
     | 
    
         
            -
                    # @return [String]
         
     | 
| 
       121 
     | 
    
         
            -
                    def self.call_template_proc(proc, controller)
         
     | 
| 
       122 
     | 
    
         
            -
                      racket = controller.racket
         
     | 
| 
       123 
     | 
    
         
            -
                      proc_args = [racket.action, racket.params, controller.request].slice(0...proc.arity)
         
     | 
| 
       124 
     | 
    
         
            -
                      proc.call(*proc_args).to_s
         
     | 
| 
       125 
     | 
    
         
            -
                    end
         
     | 
| 
       126 
     | 
    
         
            -
             
     | 
| 
       127 
     | 
    
         
            -
                    # Returns the "url path" that should be used when searching for templates.
         
     | 
| 
       128 
     | 
    
         
            -
                    #
         
     | 
| 
       129 
     | 
    
         
            -
                    # @param [Racket::Controller] controller
         
     | 
| 
       130 
     | 
    
         
            -
                    # @return [String]
         
     | 
| 
       131 
     | 
    
         
            -
                    def self.get_template_path(controller)
         
     | 
| 
       132 
     | 
    
         
            -
                      template_path =
         
     | 
| 
       133 
     | 
    
         
            -
                        [::Racket::Application.get_route(controller.class), controller.racket.action].join('/')
         
     | 
| 
       134 
     | 
    
         
            -
                      template_path = template_path[1..-1] if template_path.start_with?('//')
         
     | 
| 
       135 
     | 
    
         
            -
                      template_path
         
     | 
| 
       136 
     | 
    
         
            -
                    end
         
     | 
| 
       137 
     | 
    
         
            -
             
     | 
| 
       138 
     | 
    
         
            -
                    # Locates a file in the filesystem matching an URL path. If there exists a matching file,
         
     | 
| 
       139 
     | 
    
         
            -
                    # the path to it is returned. If there is no matching file, +nil+ is returned.
         
     | 
| 
       140 
     | 
    
         
            -
                    # @param [Pathname] path
         
     | 
| 
       141 
     | 
    
         
            -
                    # @return [Pathname|nil]
         
     | 
| 
       142 
     | 
    
         
            -
                    def self.lookup_template(path)
         
     | 
| 
       143 
     | 
    
         
            -
                      Utils.first_matching_path(*Utils.extract_dir_and_glob(path))
         
     | 
| 
       144 
     | 
    
         
            -
                    end
         
     | 
| 
       145 
     | 
    
         
            -
             
     | 
| 
       146 
     | 
    
         
            -
                    # Locates a file in the filesystem matching an URL path. If there exists a matching file,
         
     | 
| 
       147 
     | 
    
         
            -
                    # the path to it is returned. If there is no matching file and +default_template+ is a
         
     | 
| 
       148 
     | 
    
         
            -
                    # String or a Symbol, another lookup will be performed using +default_template+. If
         
     | 
| 
       149 
     | 
    
         
            -
                    # +default_template+ is a Proc or nil, +default_template+ will be used as is instead.
         
     | 
| 
       150 
     | 
    
         
            -
                    #
         
     | 
| 
       151 
     | 
    
         
            -
                    # @param [Pathname] path
         
     | 
| 
       152 
     | 
    
         
            -
                    # @param [String|Symbol|Proc|nil] default_template
         
     | 
| 
       153 
     | 
    
         
            -
                    # @return [String|Proc|nil]
         
     | 
| 
       154 
     | 
    
         
            -
                    def self.lookup_template_with_default(path, default_template)
         
     | 
| 
       155 
     | 
    
         
            -
                      template = lookup_template(path)
         
     | 
| 
       156 
     | 
    
         
            -
                      unless template
         
     | 
| 
       157 
     | 
    
         
            -
                        if default_template.is_a?(String) || default_template.is_a?(Symbol)
         
     | 
| 
       158 
     | 
    
         
            -
                          # Strings and symbols can be lookup up in the file system...
         
     | 
| 
       159 
     | 
    
         
            -
                          template = lookup_template(Utils.fs_path(path.dirname, default_template))
         
     | 
| 
       160 
     | 
    
         
            -
                        else
         
     | 
| 
       161 
     | 
    
         
            -
                          # ...but not nils/procs!
         
     | 
| 
       162 
     | 
    
         
            -
                          template = default_template
         
     | 
| 
       163 
     | 
    
         
            -
                        end
         
     | 
| 
       164 
     | 
    
         
            -
                      end
         
     | 
| 
       165 
     | 
    
         
            -
                      template
         
     | 
| 
      
 30 
     | 
    
         
            +
                  # Extracts what template settings to use based on context and incoming parameters.
         
     | 
| 
      
 31 
     | 
    
         
            +
                  #
         
     | 
| 
      
 32 
     | 
    
         
            +
                  # @param [Object] context
         
     | 
| 
      
 33 
     | 
    
         
            +
                  # @param [Hash] template_settings
         
     | 
| 
      
 34 
     | 
    
         
            +
                  # @return [Hash]
         
     | 
| 
      
 35 
     | 
    
         
            +
                  def self.extract_template_settings(context, template_settings)
         
     | 
| 
      
 36 
     | 
    
         
            +
                    if context.respond_to?(:view_settings) && !template_settings
         
     | 
| 
      
 37 
     | 
    
         
            +
                      context.view_settings
         
     | 
| 
      
 38 
     | 
    
         
            +
                    elsif template_settings
         
     | 
| 
      
 39 
     | 
    
         
            +
                      template_settings
         
     | 
| 
      
 40 
     | 
    
         
            +
                    else
         
     | 
| 
      
 41 
     | 
    
         
            +
                      {}
         
     | 
| 
       166 
42 
     | 
    
         
             
                    end
         
     | 
| 
       167 
43 
     | 
    
         
             
                  end
         
     | 
| 
       168 
     | 
    
         
            -
             
     | 
| 
       169 
     | 
    
         
            -
                  # Class responsible for rendering a controller/view/layout combination.
         
     | 
| 
       170 
     | 
    
         
            -
                  class ViewRenderer
         
     | 
| 
       171 
     | 
    
         
            -
                    # Renders a page using the provided controller/view and layout combination and returns an
         
     | 
| 
       172 
     | 
    
         
            -
                    # response array that can be sent to the client.
         
     | 
| 
       173 
     | 
    
         
            -
                    #
         
     | 
| 
       174 
     | 
    
         
            -
                    # @param [Racket::Controller] controller
         
     | 
| 
       175 
     | 
    
         
            -
                    # @param [String] view
         
     | 
| 
       176 
     | 
    
         
            -
                    # @param [String] layout
         
     | 
| 
       177 
     | 
    
         
            -
                    # @return [Array]
         
     | 
| 
       178 
     | 
    
         
            -
                    def self.render(controller, view, layout)
         
     | 
| 
       179 
     | 
    
         
            -
                      send_response(
         
     | 
| 
       180 
     | 
    
         
            -
                        controller.response,
         
     | 
| 
       181 
     | 
    
         
            -
                        view ? render_template(controller, view, layout) : controller.racket.action_result
         
     | 
| 
       182 
     | 
    
         
            -
                      )
         
     | 
| 
       183 
     | 
    
         
            -
                    end
         
     | 
| 
       184 
     | 
    
         
            -
             
     | 
| 
       185 
     | 
    
         
            -
                    # Renders a template/layout combo using Tilt and returns it as a string.
         
     | 
| 
       186 
     | 
    
         
            -
                    #
         
     | 
| 
       187 
     | 
    
         
            -
                    # @param [Racket::Controller] controller
         
     | 
| 
       188 
     | 
    
         
            -
                    # @param [String] view
         
     | 
| 
       189 
     | 
    
         
            -
                    # @param [String|nil] layout
         
     | 
| 
       190 
     | 
    
         
            -
                    # @return [String]
         
     | 
| 
       191 
     | 
    
         
            -
                    def self.render_template(controller, view, layout)
         
     | 
| 
       192 
     | 
    
         
            -
                      output = Tilt.new(view).render(controller)
         
     | 
| 
       193 
     | 
    
         
            -
                      output = Tilt.new(layout).render(controller) { output } if layout
         
     | 
| 
       194 
     | 
    
         
            -
                      output
         
     | 
| 
       195 
     | 
    
         
            -
                    end
         
     | 
| 
       196 
     | 
    
         
            -
             
     | 
| 
       197 
     | 
    
         
            -
                    # Sends response to client.
         
     | 
| 
       198 
     | 
    
         
            -
                    #
         
     | 
| 
       199 
     | 
    
         
            -
                    # @param [Racket::Response] response
         
     | 
| 
       200 
     | 
    
         
            -
                    # @param [String] output
         
     | 
| 
       201 
     | 
    
         
            -
                    # @return nil
         
     | 
| 
       202 
     | 
    
         
            -
                    def self.send_response(response, output)
         
     | 
| 
       203 
     | 
    
         
            -
                      response.write(output)
         
     | 
| 
       204 
     | 
    
         
            -
                      response.finish
         
     | 
| 
       205 
     | 
    
         
            -
                    end
         
     | 
| 
       206 
     | 
    
         
            -
             
     | 
| 
       207 
     | 
    
         
            -
                    private_class_method :render_template, :send_response
         
     | 
| 
       208 
     | 
    
         
            -
                  end
         
     | 
| 
       209 
     | 
    
         
            -
             
     | 
| 
       210 
     | 
    
         
            -
                  # Struct for holding template data.
         
     | 
| 
       211 
     | 
    
         
            -
                  TemplateParams = Struct.new(:type, :controller, :base_dir, :cache)
         
     | 
| 
       212 
44 
     | 
    
         
             
                end
         
     | 
| 
       213 
45 
     | 
    
         
             
              end
         
     | 
| 
       214 
46 
     | 
    
         
             
            end
         
     |