pancake 0.1.29 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +0 -4
- data/Rakefile +1 -32
- data/TODO.textile +19 -0
- data/bin/pancake-gen +1 -0
- data/lib/pancake.rb +26 -39
- data/lib/pancake/bootloaders.rb +2 -2
- data/lib/pancake/configuration.rb +1 -1
- data/lib/pancake/core_ext/class.rb +3 -3
- data/lib/pancake/errors.rb +6 -8
- data/lib/pancake/generators.rb +1 -0
- data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%/config/environments/development.rb.tt +0 -3
- data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%/config/environments/production.rb.tt +0 -3
- data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%/config/environments/staging.rb.tt +0 -3
- data/lib/pancake/hooks/inheritable_inner_classes.rb +9 -10
- data/lib/pancake/hooks/on_inherit.rb +7 -7
- data/lib/pancake/logger.rb +1 -14
- data/lib/pancake/master.rb +7 -45
- data/lib/pancake/middleware.rb +11 -64
- data/lib/pancake/mixins/publish.rb +20 -20
- data/lib/pancake/mixins/render.rb +59 -69
- data/lib/pancake/mixins/render/template.rb +1 -1
- data/lib/pancake/mixins/render/view_context.rb +143 -7
- data/lib/pancake/mixins/request_helper.rb +38 -1
- data/lib/pancake/mixins/stack_helper.rb +2 -2
- data/lib/pancake/paths.rb +1 -1
- data/lib/pancake/router.rb +10 -2
- data/lib/pancake/stack/bootloader.rb +12 -1
- data/lib/pancake/stack/router.rb +2 -1
- data/lib/pancake/stack/stack.rb +60 -2
- data/lib/pancake/stacks/short/controller.rb +58 -3
- data/lib/pancake/stacks/short/default/views/base.html.haml +1 -1
- data/lib/pancake/stacks/short/default/views/error.html.haml +12 -0
- data/lib/pancake/stacks/short/stack.rb +1 -0
- data/spec/pancake/fixtures/render_templates/alternate.foo_env.html.haml +1 -0
- data/spec/pancake/fixtures/render_templates/alternate.html.haml +1 -0
- data/spec/pancake/fixtures/render_templates/view_context/capture_erb.erb +1 -1
- data/spec/pancake/fixtures/render_templates/view_context/capture_haml.haml +1 -1
- data/spec/pancake/fixtures/render_templates/view_context/concat_erb.erb +1 -1
- data/spec/pancake/fixtures/render_templates/view_context/concat_haml.haml +2 -1
- data/spec/pancake/middleware_spec.rb +4 -26
- data/spec/pancake/mixins/render/view_context_spec.rb +15 -23
- data/spec/pancake/mixins/render_spec.rb +54 -0
- data/spec/pancake/pancake_spec.rb +0 -22
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +1 -0
- metadata +193 -108
- data/TODO +0 -7
- data/bin/jeweler +0 -19
- data/lib/pancake/mixins/render/render.rb +0 -197
data/lib/pancake/middleware.rb
CHANGED
@@ -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
|
63
|
-
|
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
|
-
|
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
|
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
|
183
|
+
def middlewares
|
211
184
|
_central_mwares.map do |name|
|
212
|
-
map_middleware(name
|
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
|
198
|
+
def map_middleware(name)
|
233
199
|
result = []
|
234
200
|
_before[name] ||= []
|
235
201
|
_after[name] ||= []
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
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
|
-
|
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
|
16
|
-
|
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
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
45
|
-
|
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
|
-
|
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(
|
61
|
-
[
|
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
|
-
|
66
|
-
"#{name}.#{opts[:format]}"
|
64
|
+
def _template_name_for(name, opts)
|
65
|
+
"#{name}"
|
67
66
|
end
|
68
67
|
|
69
|
-
def template(
|
70
|
-
case
|
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
|
-
|
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
|
-
|
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(
|
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(
|
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(
|
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
|
|