pancake 0.1.29 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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