pancake 0.1.29 → 0.2.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.
Files changed (49) hide show
  1. data/README.textile +0 -4
  2. data/Rakefile +1 -32
  3. data/TODO.textile +19 -0
  4. data/bin/pancake-gen +1 -0
  5. data/lib/pancake.rb +26 -39
  6. data/lib/pancake/bootloaders.rb +2 -2
  7. data/lib/pancake/configuration.rb +1 -1
  8. data/lib/pancake/core_ext/class.rb +3 -3
  9. data/lib/pancake/errors.rb +6 -8
  10. data/lib/pancake/generators.rb +1 -0
  11. data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%/config/environments/development.rb.tt +0 -3
  12. data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%/config/environments/production.rb.tt +0 -3
  13. data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%/config/environments/staging.rb.tt +0 -3
  14. data/lib/pancake/hooks/inheritable_inner_classes.rb +9 -10
  15. data/lib/pancake/hooks/on_inherit.rb +7 -7
  16. data/lib/pancake/logger.rb +1 -14
  17. data/lib/pancake/master.rb +7 -45
  18. data/lib/pancake/middleware.rb +11 -64
  19. data/lib/pancake/mixins/publish.rb +20 -20
  20. data/lib/pancake/mixins/render.rb +59 -69
  21. data/lib/pancake/mixins/render/template.rb +1 -1
  22. data/lib/pancake/mixins/render/view_context.rb +143 -7
  23. data/lib/pancake/mixins/request_helper.rb +38 -1
  24. data/lib/pancake/mixins/stack_helper.rb +2 -2
  25. data/lib/pancake/paths.rb +1 -1
  26. data/lib/pancake/router.rb +10 -2
  27. data/lib/pancake/stack/bootloader.rb +12 -1
  28. data/lib/pancake/stack/router.rb +2 -1
  29. data/lib/pancake/stack/stack.rb +60 -2
  30. data/lib/pancake/stacks/short/controller.rb +58 -3
  31. data/lib/pancake/stacks/short/default/views/base.html.haml +1 -1
  32. data/lib/pancake/stacks/short/default/views/error.html.haml +12 -0
  33. data/lib/pancake/stacks/short/stack.rb +1 -0
  34. data/spec/pancake/fixtures/render_templates/alternate.foo_env.html.haml +1 -0
  35. data/spec/pancake/fixtures/render_templates/alternate.html.haml +1 -0
  36. data/spec/pancake/fixtures/render_templates/view_context/capture_erb.erb +1 -1
  37. data/spec/pancake/fixtures/render_templates/view_context/capture_haml.haml +1 -1
  38. data/spec/pancake/fixtures/render_templates/view_context/concat_erb.erb +1 -1
  39. data/spec/pancake/fixtures/render_templates/view_context/concat_haml.haml +2 -1
  40. data/spec/pancake/middleware_spec.rb +4 -26
  41. data/spec/pancake/mixins/render/view_context_spec.rb +15 -23
  42. data/spec/pancake/mixins/render_spec.rb +54 -0
  43. data/spec/pancake/pancake_spec.rb +0 -22
  44. data/spec/spec.opts +2 -0
  45. data/spec/spec_helper.rb +1 -0
  46. metadata +193 -108
  47. data/TODO +0 -7
  48. data/bin/jeweler +0 -19
  49. data/lib/pancake/mixins/render/render.rb +0 -197
@@ -47,21 +47,15 @@ module Pancake
47
47
 
48
48
  # @param [Array<Symbol>] labels An array of labels specifying the stack labels to use to build the middlware list
49
49
  #
50
- # @example
51
- # MyApp.middlewares(:production) # provides all middlewares matching the :production label, or the implicit :any label
52
- # MyApp.middlewares(:development, :demo) # provides all middlewares matching the :development or :demo or implicit :any label
53
- #
54
50
  # @return [Array<StackMiddleware>]
55
51
  # An array of middleware specifications in the order they should be used to wrap the application
56
52
  #
57
53
  # @see Pancake::Middleware::StackMiddleware
58
- # @see Pancake.stack_labels for a decription of stack_labels
59
54
  # @api public
60
55
  # @since 0.1.0
61
56
  # @author Daniel Neighman
62
- def middlewares(*labels)
63
- labels = labels.flatten
64
- self::StackMiddleware.middlewares(*labels)
57
+ def middlewares
58
+ self::StackMiddleware.middlewares
65
59
  end
66
60
 
67
61
  # Useful for adding additional information into your middleware stack definition
@@ -70,8 +64,6 @@ module Pancake
70
64
  # The name of a given middleware. Each piece of middleware has a name in the stack.
71
65
  # By naming middleware we can refer to it later, swap it out for a different class or even just remove it from the stack.
72
66
  # @param [Hash] opts An options hash
73
- # @option opts [Array<Symbol>] :labels ([:any])
74
- # An array of symbols, or a straight symbol that defines what stacks this middleware sould be active in
75
67
  # @option opts [Object] :before
76
68
  # Sets this middlware to be run after the middleware named. Name is either the name given to the
77
69
  # middleware stack, or the Middleware class itself.
@@ -101,15 +93,6 @@ module Pancake
101
93
  # This middleware will be named :foo and will be run after the middleware named :bar
102
94
  # If :bar is not run, :foo will not be run either
103
95
  #
104
- # @example Declaring a named middleware with some labels
105
- # MyClass.stack(:foo, :lables => [:demo, :production, :staging]).use(MyMiddleware)
106
- #
107
- # This middleware will only be run when pancake is set with the :demo, :production or :staging labels
108
- #
109
- # @example A full example
110
- # MyClass.stack(:foo, :labels => [:staging, :development], :after => :session).use(MyMiddleware)
111
- #
112
- #
113
96
  # @see Pancake::Middleware#use
114
97
  # @api public
115
98
  # @since 0.1.0
@@ -165,7 +148,7 @@ module Pancake
165
148
  # the StackMiddleware class is inherited to an inner class of the same name on the child.
166
149
  class StackMiddleware
167
150
  # @api private
168
- class_inheritable_reader :_central_mwares, :_mwares, :_before, :_after
151
+ extlib_inheritable_reader :_central_mwares, :_mwares, :_before, :_after
169
152
  @_central_mwares, @_before, @_after, @_mwares = [], {}, {}, {}
170
153
 
171
154
  # @api private
@@ -186,17 +169,7 @@ module Pancake
186
169
  _after.clear
187
170
  end
188
171
 
189
- # Get the middleware list for this StackMiddleware for the given labels
190
- #
191
- # @param [Symbol] labels The label or list of labels to construct a stack from.
192
- #
193
- # @example Specified labels
194
- # MyClass::StackMiddleware.middlewares(:production, :demo)
195
- #
196
- # @example No Labels Specified
197
- # MyClass::StackMiddleware.middlewares
198
- #
199
- # This will include all defined middlewares in the given stack
172
+ # Get the middleware list for this StackMiddleware
200
173
  #
201
174
  # @return [Array<StackMiddleware>]
202
175
  # An array of the middleware definitions to use in the order that they should be applied
@@ -207,39 +180,29 @@ module Pancake
207
180
  # @api public
208
181
  # @since 0.1.0
209
182
  # @author Daniel Neighman
210
- def middlewares(*labels)
183
+ def middlewares
211
184
  _central_mwares.map do |name|
212
- map_middleware(name, *labels)
185
+ map_middleware(name)
213
186
  end.flatten
214
187
  end
215
188
 
216
189
  # Map the middleware for a given <name>ed middleware. Applies the before and after groups of middlewares
217
190
  #
218
191
  # @param [Object] name The name of the middleware to map the before and after groups to
219
- # @param [Symbol] labels A label or list of labels to use to construct the middleware stack
220
- #
221
- # @example
222
- # MyClass::StackMiddleware.map_middleware(:foo, :production, :demo)
223
- #
224
- # Constructs the middleware list based on the middleware named :foo, including all :before, and :after groups
225
- #
226
192
  # @return [Array<StackMiddleware>]
227
193
  # Provides an array of StackMiddleware instances in the array [<before :foo>, <:foo>, <after :foo>]
228
194
  #
229
195
  # @api private
230
196
  # @since 0.1.0
231
197
  # @author Daniel Neighman
232
- def map_middleware(name, *labels)
198
+ def map_middleware(name)
233
199
  result = []
234
200
  _before[name] ||= []
235
201
  _after[name] ||= []
236
- if _mwares[name] && _mwares[name].use_for_labels?(*labels)
237
- result << _before[name].map{|n| map_middleware(n)}
238
- result << _mwares[name]
239
- result << _after[name].map{|n| map_middleware(n)}
240
- result.flatten
241
- end
242
- result
202
+ result << _before[name].map{|n| map_middleware(n)}
203
+ result << _mwares[name]
204
+ result << _after[name].map{|n| map_middleware(n)}
205
+ result.flatten
243
206
  end
244
207
 
245
208
  # Provides access to a named middleware
@@ -268,8 +231,6 @@ module Pancake
268
231
  # @param [Object] name a name for this middleware definition. Usually a symbol, but could be the class.
269
232
  # @param [Object] stack the stack owner of this middleware.
270
233
  # @param [Hash] options an options hash. Provide labels for this middleware.
271
- # @option options [Array] :labels ([:any])
272
- # The labels that are associated with this middleware
273
234
  # @option options [Object] :before A middleware name to add this middleware before
274
235
  # @option options [Object] :after A middleware name to add this middleware after
275
236
  #
@@ -278,7 +239,6 @@ module Pancake
278
239
  # @author Daniel Neighman
279
240
  def initialize(name, stack, options = {})
280
241
  @name, @stack, @options = name, stack, options
281
- @options[:labels] ||= [:any]
282
242
  end
283
243
 
284
244
  # Delete this middleware from the current stack
@@ -322,19 +282,6 @@ module Pancake
322
282
  self
323
283
  end
324
284
 
325
- # Checks if this middleware definition should be included from the labels given
326
- # @param [Symbol] labels The label or list of labels to check if this middleware should be included
327
- #
328
- # @return [Boolean] true if this middlware should be included
329
- #
330
- # @api private
331
- # @since 0.1.0
332
- # @author Daniel Neighman
333
- def use_for_labels?(*labels)
334
- return true if labels.empty? || options[:labels].nil? || options[:labels].include?(:any)
335
- !(options[:labels] & labels).empty?
336
- end
337
-
338
285
  # @api private
339
286
  def dup
340
287
  result = super
@@ -2,17 +2,17 @@ require File.join(File.dirname(__FILE__), "publish", "action_options")
2
2
  module Pancake
3
3
  module Mixins
4
4
  module Publish
5
-
5
+
6
6
  def self.extended(base)
7
7
  base.class_eval do
8
- class_inheritable_accessor :actions, :formats
8
+ extlib_inheritable_accessor :actions, :formats
9
9
  self.actions = {}
10
10
  self.formats = [:html]
11
11
  end
12
12
  end
13
-
13
+
14
14
  # Accepts a list of symbols representing the formats each action in the
15
- # controller will return. By default the list consists only of :html
15
+ # controller will return. By default the list consists only of :html
16
16
  #
17
17
  # provides :html, :xml
18
18
  #
@@ -20,9 +20,9 @@ module Pancake
20
20
  def provides(*args)
21
21
  self.formats = args
22
22
  end
23
-
24
- # Causes the next method added immediately after it’s call to be defined
25
- # as an action. It also generates an instance of ActionOptions, which
23
+
24
+ # Causes the next method added immediately after it’s call to be defined
25
+ # as an action. It also generates an instance of ActionOptions, which
26
26
  # encapsulates all the parameters the action accepts/expects and also
27
27
  # the formats that it can potentially return.
28
28
  #
@@ -31,13 +31,13 @@ module Pancake
31
31
  # ...
32
32
  # end
33
33
  #
34
- # The example above publishes the action "show" and configures the
34
+ # The example above publishes the action "show" and configures the
35
35
  # following options for it:
36
36
  #
37
37
  # - The parameter 'id' will be coerced into an Integer
38
38
  # - It also must not be blank, it is required.
39
39
  #
40
- # The publish declaration can also create much more sophisticated
40
+ # The publish declaration can also create much more sophisticated
41
41
  # constraints. You can declare a parameter as optional, give it a default
42
42
  # value if it is missing.
43
43
  #
@@ -52,9 +52,9 @@ module Pancake
52
52
  # #publish can also handle the specification of formats for an action. It
53
53
  # accepts an additional two options, :provides and :only_provides.
54
54
  #
55
- # To the list of globally declared formats, :provides adds additional
55
+ # To the list of globally declared formats, :provides adds additional
56
56
  # formats to an action.
57
- #
57
+ #
58
58
  # publish :provides => :xml
59
59
  #
60
60
  # The :only_provides option overrides any globally declared formats for an
@@ -66,9 +66,9 @@ module Pancake
66
66
  def publish(opts = {})
67
67
  @pending_publication_opts = opts
68
68
  end
69
-
69
+
70
70
  # Used when declaring configuration for parameters in the publish
71
- # declaration. It returns an array of the type, default value an
71
+ # declaration. It returns an array of the type, default value an
72
72
  # additional options.
73
73
  #
74
74
  # @param type [Object] The
@@ -78,7 +78,7 @@ module Pancake
78
78
  # - :date
79
79
  # - :string
80
80
  #
81
- # For details on the options supported by each type, please see the
81
+ # For details on the options supported by each type, please see the
82
82
  # corresponding methods declared in the ActionOptions class. These methods
83
83
  # are named as the type, prefixed with 'validate_and_coerce_'
84
84
  #
@@ -96,9 +96,9 @@ module Pancake
96
96
  def as(type, default = :req, opts = {})
97
97
  [type, default, opts]
98
98
  end
99
-
99
+
100
100
  # Takes a parameters hash, and validates each entry against the options
101
- # defined for this action. It will flag required params when missing,
101
+ # defined for this action. It will flag required params when missing,
102
102
  # insert defaults or coerce values into the desired type. It mutates
103
103
  # the params hash itself.
104
104
  #
@@ -106,10 +106,10 @@ module Pancake
106
106
  def validate_and_coerce_params(action, params)
107
107
  actions[action].validate_and_coerce(params)
108
108
  end
109
-
110
-
111
- # This hook is used in conjunction with the #publish method to expose
112
- # instance methods as actions. Obviously, it should never be called
109
+
110
+
111
+ # This hook is used in conjunction with the #publish method to expose
112
+ # instance methods as actions. Obviously, it should never be called
113
113
  # directly :)
114
114
  #
115
115
  # @api private
@@ -1,5 +1,4 @@
1
1
  require 'pancake/mixins/render/template'
2
- require 'pancake/mixins/render/render'
3
2
  require 'pancake/mixins/render/view_context'
4
3
  module Pancake
5
4
  module Mixins
@@ -10,11 +9,9 @@ module Pancake
10
9
  base.class_eval do
11
10
  extend Pancake::Mixins::Render::ClassMethods
12
11
  include Pancake::Mixins::Render::InstanceMethods
13
- include Pancake::Mixins::RequestHelper
14
12
 
15
- class self::ViewContext < Pancake::Mixins::Render::ViewContext
16
- include Pancake::Mixins::RequestHelper
17
- end
13
+ class base::ViewContext < Pancake::Mixins::Render::ViewContext; end
14
+
18
15
  inheritable_inner_classes :ViewContext
19
16
 
20
17
  unless ancestors.include?(Pancake::Paths)
@@ -33,16 +30,19 @@ module Pancake
33
30
  @_template_cache ||= {}
34
31
  end
35
32
 
36
- def _find_template(name)
37
- renderer = _template_cache[name]
38
- return renderer if renderer
39
-
40
- renderer_path = unique_paths_for(:views, :invert => true).detect do |path|
41
- path.last =~ %r[^\/?(#{name})\.\w+$]
42
- end
33
+ # Allows you to set path label for the templates for this class
34
+ #
35
+ # @example
36
+ # MyClass.push_paths(:my_templates, "somewhere", "**/*")
37
+ #
38
+ # MyClass._template_path_name #=> :my_templates
39
+ # @api public
40
+ def _template_path_name(opts = {})
41
+ opts[:template_path_name] || :views
42
+ end
43
43
 
44
- raise TemplateNotFound unless renderer_path
45
- _template_cache[name] = Template.new(name, self, renderer_path.join)
44
+ def _find_template(name, opts = {})
45
+ template(name, opts)
46
46
  end
47
47
 
48
48
  def _view_context_cache
@@ -52,26 +52,55 @@ module Pancake
52
52
 
53
53
  def _find_view_context_class_for(template)
54
54
  _view_context_cache[template] ||= begin
55
- Class.new(self::ViewContext)
55
+ self::ViewContext
56
56
  end
57
57
  _view_context_cache[template]
58
58
  end
59
59
 
60
- def _renderer_and_view_context_class_for(template)
61
- [_find_template(template), _find_view_context_class_for(template)]
60
+ def _renderer_and_view_context_class_for(tplate)
61
+ [template(tplate), _find_view_context_class_for(tplate)]
62
62
  end
63
63
 
64
- def _template_name_for(name, opts = {})
65
- opts[:format] ||= :html
66
- "#{name}.#{opts[:format]}"
64
+ def _template_name_for(name, opts)
65
+ "#{name}"
67
66
  end
68
67
 
69
- def template(name_or_template, opts = {})
70
- case name_or_template
71
- when String, Symbol
72
- _find_template(_template_name_for(name_or_template, opts))
68
+ def template(name, opts = {})
69
+ case name
73
70
  when Template
74
- name_or_template
71
+ name
72
+ when String, Symbol
73
+
74
+ template_names = case __template = _template_name_for(name, opts)
75
+ when String, Symbol
76
+ [__template]
77
+ when Array
78
+ __template
79
+ when Proc
80
+ [__template.call(opts)].flatten
81
+ else
82
+ nil
83
+ end
84
+
85
+ renderer = _template_cache[template_names]
86
+ return renderer if renderer
87
+
88
+ unique_paths = unique_paths_for(_template_path_name(opts), :invert => true)
89
+
90
+ renderer_path = nil
91
+ template_name = nil
92
+
93
+ template_names.detect do |tn|
94
+ unique_paths.detect do |path|
95
+ if path.last =~ %r[^\/?(#{tn})\.\w+$]
96
+ template_name = tn
97
+ renderer_path = path.join
98
+ end
99
+ end
100
+ end
101
+
102
+ raise TemplateNotFound unless renderer_path
103
+ _template_cache[template_names] = Template.new(template_name, self, renderer_path)
75
104
  else
76
105
  nil
77
106
  end
@@ -87,15 +116,15 @@ module Pancake
87
116
  def render(*args)
88
117
  opts = Hash === args.last ? args.pop : {}
89
118
  name = args.shift
90
- template_name = _template_name_for(name, opts)
119
+ template = self.class.template(name, opts)
91
120
  return opts[:text] if opts[:text]
92
121
 
93
122
  # Get the view context for the tempalte
94
- template, vc_class = self.class._renderer_and_view_context_class_for(template_name)
123
+ template, vc_class = self.class._renderer_and_view_context_class_for(template)
95
124
 
96
125
  yield v if block_given?
97
126
 
98
- view_context = vc_class.new(env, self)
127
+ view_context = vc_class.new(self)
99
128
  view_context_before_render(view_context)
100
129
  view_context.render(template, opts)
101
130
  end
@@ -111,7 +140,7 @@ module Pancake
111
140
  # Get the view context for the tempalte
112
141
  template, vc_class = self.class._renderer_and_view_context_class_for(partial_name)
113
142
 
114
- view_context = vc_class.new(env, self)
143
+ view_context = vc_class.new(self)
115
144
  view_context_before_render(view_context)
116
145
 
117
146
  out = ""
@@ -129,48 +158,9 @@ module Pancake
129
158
  end
130
159
 
131
160
  def template(name_or_template, opts = {})
132
- opts[:format] ||= content_type
133
161
  self.class.template(name_or_template, opts)
134
162
  end
135
163
 
136
- def negotiate_content_type!(*allowed_types)
137
- return content_type if content_type
138
-
139
- allowed_types = allowed_types.flatten
140
- opts = allowed_types.pop if allowed_types.last.kind_of?(Hash)
141
- if opts[:format]
142
- cont, ct, mt = Pancake::MimeTypes.negotiate_by_extension(opts[:format].to_s, allowed_types)
143
- else
144
- env["HTTP_ACCEPT"] ||= "*/*"
145
- cont, ct, mt = Pancake::MimeTypes.negotiate_accept_type(env["HTTP_ACCEPT"], allowed_types)
146
- end
147
-
148
- raise Errors::NotAcceptable unless cont
149
-
150
- headers["Content-Type"] = ct
151
- self.mime_type = mt
152
- self.content_type = cont
153
- cont
154
- end
155
-
156
- def content_type
157
- env['pancake.request.format']
158
- end
159
-
160
- def content_type=(format)
161
- env['pancake.request.format'] = format
162
- end
163
-
164
- def mime_type
165
- env['pancake.request.mime']
166
- end
167
-
168
- def mime_type=(mime)
169
- env['pancake.request.mime'] = mime
170
- end
171
-
172
-
173
-
174
164
  # A place holder method for any implementor that wants
175
165
  # to configure the view context prior to rendering occuring
176
166
  # any time this method is overwritten, it should call super!
@@ -180,8 +170,8 @@ module Pancake
180
170
  end
181
171
 
182
172
  private
173
+ # @api_overwritable
183
174
  def _template_name_for(name, opts = {})
184
- opts[:format] ||= content_type
185
175
  self.class._template_name_for(name, opts)
186
176
  end
187
177