hassox-pancake 0.1.6
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.
- data/LICENSE +20 -0
- data/README.textile +95 -0
- data/Rakefile +56 -0
- data/TODO +18 -0
- data/bin/jeweler +19 -0
- data/bin/pancake-gen +17 -0
- data/bin/rubyforge +19 -0
- data/lib/pancake.rb +48 -0
- data/lib/pancake/bootloaders.rb +180 -0
- data/lib/pancake/configuration.rb +140 -0
- data/lib/pancake/core_ext/class.rb +44 -0
- data/lib/pancake/core_ext/object.rb +22 -0
- data/lib/pancake/core_ext/symbol.rb +15 -0
- data/lib/pancake/errors.rb +61 -0
- data/lib/pancake/generators.rb +8 -0
- data/lib/pancake/generators/base.rb +12 -0
- data/lib/pancake/generators/flat_generator.rb +17 -0
- data/lib/pancake/generators/short_generator.rb +17 -0
- data/lib/pancake/generators/stack_generator.rb +17 -0
- data/lib/pancake/generators/templates/common/dotgitignore +22 -0
- data/lib/pancake/generators/templates/common/dothtaccess +17 -0
- data/lib/pancake/generators/templates/flat/%stack_name%/%stack_name%.rb.tt +8 -0
- data/lib/pancake/generators/templates/flat/%stack_name%/.gitignore +21 -0
- data/lib/pancake/generators/templates/flat/%stack_name%/config.ru.tt +12 -0
- data/lib/pancake/generators/templates/flat/%stack_name%/pancake.init.tt +1 -0
- data/lib/pancake/generators/templates/flat/%stack_name%/public/.empty_directory +0 -0
- data/lib/pancake/generators/templates/flat/%stack_name%/tmp/.empty_directory +0 -0
- data/lib/pancake/generators/templates/short/%stack_name%/.gitignore +21 -0
- data/lib/pancake/generators/templates/short/%stack_name%/LICENSE.tt +20 -0
- data/lib/pancake/generators/templates/short/%stack_name%/README.tt +7 -0
- data/lib/pancake/generators/templates/short/%stack_name%/Rakefile.tt +48 -0
- data/lib/pancake/generators/templates/short/%stack_name%/VERSION.tt +1 -0
- data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%.rb.tt +5 -0
- data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%/%stack_name%.rb.tt +6 -0
- data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%/config.ru.tt +12 -0
- data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%/gems/cache/.empty_directory +0 -0
- data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%/mounts/.empty_directory +0 -0
- data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%/public/.empty_directory +0 -0
- data/lib/pancake/generators/templates/short/%stack_name%/lib/%stack_name%/tmp/.empty_directory +0 -0
- data/lib/pancake/generators/templates/short/%stack_name%/pancake.init.tt +1 -0
- data/lib/pancake/generators/templates/short/%stack_name%/spec/%stack_name%_spec.rb.tt +7 -0
- data/lib/pancake/generators/templates/short/%stack_name%/spec/spec_helper.rb.tt +9 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/.gitignore +21 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/LICENSE.tt +20 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/README.tt +7 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/Rakefile.tt +48 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/VERSION.tt +1 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/lib/%stack_name%.rb.tt +3 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/lib/%stack_name%/config.ru.tt +12 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/lib/%stack_name%/config/environments/development.rb.tt +18 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/lib/%stack_name%/config/environments/production.rb.tt +18 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/lib/%stack_name%/config/router.rb.tt +6 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/lib/%stack_name%/gems/cache/.empty_directory +0 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/lib/%stack_name%/mounts/.empty_directory +0 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/lib/%stack_name%/public/.empty_directory +0 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/lib/%stack_name%/tmp/.empty_directory +0 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/pancake.init.tt +1 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/spec/%stack_name%_spec.rb.tt +7 -0
- data/lib/pancake/generators/templates/stack/%stack_name%/spec/spec_helper.rb.tt +9 -0
- data/lib/pancake/hooks/inheritable_inner_classes.rb +60 -0
- data/lib/pancake/hooks/on_inherit.rb +34 -0
- data/lib/pancake/master.rb +87 -0
- data/lib/pancake/middleware.rb +354 -0
- data/lib/pancake/mime_types.rb +265 -0
- data/lib/pancake/mixins/publish.rb +125 -0
- data/lib/pancake/mixins/publish/action_options.rb +104 -0
- data/lib/pancake/mixins/render.rb +61 -0
- data/lib/pancake/mixins/request_helper.rb +92 -0
- data/lib/pancake/mixins/stack_helper.rb +44 -0
- data/lib/pancake/mixins/url.rb +10 -0
- data/lib/pancake/more/controller.rb +4 -0
- data/lib/pancake/more/controller/base.rb +34 -0
- data/lib/pancake/paths.rb +218 -0
- data/lib/pancake/router.rb +99 -0
- data/lib/pancake/stack/app.rb +10 -0
- data/lib/pancake/stack/bootloader.rb +79 -0
- data/lib/pancake/stack/configuration.rb +44 -0
- data/lib/pancake/stack/middleware.rb +0 -0
- data/lib/pancake/stack/router.rb +18 -0
- data/lib/pancake/stack/stack.rb +57 -0
- data/lib/pancake/stacks/short.rb +2 -0
- data/lib/pancake/stacks/short/controller.rb +105 -0
- data/lib/pancake/stacks/short/stack.rb +194 -0
- data/spec/helpers/helpers.rb +20 -0
- data/spec/helpers/matchers.rb +25 -0
- data/spec/pancake/bootloaders_spec.rb +109 -0
- data/spec/pancake/configuration_spec.rb +177 -0
- data/spec/pancake/fixtures/foo_stack/pancake.init +0 -0
- data/spec/pancake/fixtures/paths/controllers/controller1.rb +0 -0
- data/spec/pancake/fixtures/paths/controllers/controller2.rb +0 -0
- data/spec/pancake/fixtures/paths/controllers/controller3.rb +0 -0
- data/spec/pancake/fixtures/paths/models/model1.rb +0 -0
- data/spec/pancake/fixtures/paths/models/model2.rb +0 -0
- data/spec/pancake/fixtures/paths/models/model3.rb +0 -0
- data/spec/pancake/fixtures/paths/stack/controllers/controller1.rb +0 -0
- data/spec/pancake/fixtures/paths/stack/models/model3.rb +0 -0
- data/spec/pancake/fixtures/paths/stack/views/view1.erb +0 -0
- data/spec/pancake/fixtures/paths/stack/views/view1.rb +0 -0
- data/spec/pancake/fixtures/paths/stack/views/view2.erb +0 -0
- data/spec/pancake/fixtures/paths/stack/views/view2.haml +0 -0
- data/spec/pancake/fixtures/render_templates/context_template.html.erb +1 -0
- data/spec/pancake/fixtures/render_templates/erb_template.html.erb +1 -0
- data/spec/pancake/fixtures/render_templates/erb_template.json.erb +1 -0
- data/spec/pancake/fixtures/render_templates/haml_template.html.haml +1 -0
- data/spec/pancake/fixtures/render_templates/haml_template.xml.haml +1 -0
- data/spec/pancake/hooks/on_inherit_spec.rb +65 -0
- data/spec/pancake/inheritance_spec.rb +100 -0
- data/spec/pancake/middleware_spec.rb +401 -0
- data/spec/pancake/mime_types_spec.rb +234 -0
- data/spec/pancake/mixins/publish_spec.rb +94 -0
- data/spec/pancake/mixins/render_spec.rb +55 -0
- data/spec/pancake/mixins/stack_helper_spec.rb +46 -0
- data/spec/pancake/pancake_spec.rb +31 -0
- data/spec/pancake/paths_spec.rb +210 -0
- data/spec/pancake/stack/app_spec.rb +28 -0
- data/spec/pancake/stack/bootloader_spec.rb +41 -0
- data/spec/pancake/stack/middleware_spec.rb +0 -0
- data/spec/pancake/stack/router_spec.rb +266 -0
- data/spec/pancake/stack/stack_configuration_spec.rb +101 -0
- data/spec/pancake/stack/stack_spec.rb +55 -0
- data/spec/pancake/stacks/short/controller_spec.rb +287 -0
- data/spec/pancake/stacks/short/router_spec.rb +132 -0
- data/spec/pancake/stacks/short/stack_spec.rb +40 -0
- data/spec/spec_helper.rb +21 -0
- metadata +238 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Pancake
|
|
2
|
+
# TODOS:
|
|
3
|
+
# * Sketch out how action dispatch will work
|
|
4
|
+
# * What helpers do we need for dealing with different formats?
|
|
5
|
+
# * What are the different errors that might arise in dispatch? 404 etc.
|
|
6
|
+
# * Get before and after hooks working. These wrap around all action calls
|
|
7
|
+
# by default, so the hooks in extlib aren’t useful. Additionally, the
|
|
8
|
+
# the dispatch step gives us a point to hook in before and after the call.
|
|
9
|
+
class Controller
|
|
10
|
+
extend Mixins::Publish
|
|
11
|
+
|
|
12
|
+
def self.call(env)
|
|
13
|
+
new(env)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def initialize(env)
|
|
17
|
+
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Returns the rack environment
|
|
21
|
+
def request
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Returns a hash of parameters
|
|
26
|
+
def params
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def render(opts = {})
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
end # Controller
|
|
34
|
+
end # Pancake
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
module Pancake
|
|
2
|
+
# Pancake::Paths provides a mixin for path management.
|
|
3
|
+
# A path consists of a name, and paths + globs, and makes use of the Klass.roots that have been set as
|
|
4
|
+
# file roots for each path and glob to be applied to.
|
|
5
|
+
# Each name may have many (path + glob)s, so that many root paths may be added to the same name
|
|
6
|
+
#
|
|
7
|
+
# @example Adding Paths:
|
|
8
|
+
# class Foo
|
|
9
|
+
# extend Pancake::Paths
|
|
10
|
+
# end
|
|
11
|
+
#
|
|
12
|
+
# Foo.push_paths(:model, "relative/path/to/models", "**/*.rb")
|
|
13
|
+
# Foo.push_paths(:model, "another/path/to/models", "**/*.rb")
|
|
14
|
+
# Foo.push_paths(:model, "yet/another")
|
|
15
|
+
#
|
|
16
|
+
# This will make available the directory and or full file paths for :model in the order they
|
|
17
|
+
# were declared.
|
|
18
|
+
#
|
|
19
|
+
# When no glob is provided, the glob will be returned as nil
|
|
20
|
+
#
|
|
21
|
+
# @example Reading Paths:
|
|
22
|
+
# Foo.dirs_for(:model) == ["#{root}/relative/path/to/models", "#{root}/another/path/to/models", "#{root}/yet/another"]
|
|
23
|
+
#
|
|
24
|
+
# Foo.dirs_and_glob_for(:model) == [
|
|
25
|
+
# ["#{root}/relative/path/to/models", "**/*.rb"],
|
|
26
|
+
# ["#{root}//another/path/to/models", "**/*.rb"],
|
|
27
|
+
# ["#{root}//yet/another", nil]
|
|
28
|
+
# ]
|
|
29
|
+
#
|
|
30
|
+
# Foo.paths_for(:model) == [
|
|
31
|
+
# ["#{root}/relative/path/to/models", "/model1.rb"],
|
|
32
|
+
# ["#{root}/path/to/models", "/model2.rb"],
|
|
33
|
+
# ["#{root}/path/to/models/sub", "/model1.rb"],
|
|
34
|
+
# ["#{root}/another/path/to/models", "/model3.rb"]
|
|
35
|
+
# ]
|
|
36
|
+
#
|
|
37
|
+
# The paths are fully inheritable once they have extended a class.
|
|
38
|
+
module Paths
|
|
39
|
+
class NoPathsGiven < ArgumentError; end
|
|
40
|
+
|
|
41
|
+
def self.extended(base) #:nodoc:#
|
|
42
|
+
base.class_eval do
|
|
43
|
+
deep_copy_class_inheritable_reader :_load_paths, :roots
|
|
44
|
+
@_load_paths = Dictionary.new
|
|
45
|
+
@roots = []
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Push a named path and optional glob onto the list of paths associated with <name>
|
|
50
|
+
#
|
|
51
|
+
# @param [Symbol] name The name to associate with the given path and glob
|
|
52
|
+
# @param [String, Array] paths A path or paths to associate with the namd and glob
|
|
53
|
+
# @param [String, Nil] glob The glob to associate with the given path(s) and name
|
|
54
|
+
#
|
|
55
|
+
# @example No Glob:
|
|
56
|
+
# MyClass.push_paths(:foo, "path/for/foo")
|
|
57
|
+
#
|
|
58
|
+
# @example Using a Glob:
|
|
59
|
+
# MyClass.push_paths(:foo, "path/for/foo", "**/*.rb")
|
|
60
|
+
#
|
|
61
|
+
# @example Using Multiple paths:
|
|
62
|
+
# MyClass.push_paths(:foo, ["path/one", "path/two"], "**/*.rb")
|
|
63
|
+
#
|
|
64
|
+
# @raise [Pancake::NoPathsGiven] raised when an empty paths array is provided
|
|
65
|
+
# @author Daniel Neighman
|
|
66
|
+
# @since 0.1.1
|
|
67
|
+
# @api public
|
|
68
|
+
def push_paths(name, paths, glob = nil)
|
|
69
|
+
paths = [paths].flatten
|
|
70
|
+
raise NoPathsGiven if paths.blank?
|
|
71
|
+
_load_paths[name] ||= []
|
|
72
|
+
_load_paths[name] << [paths, glob]
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Provides the directories or raw paths that are associated with a given name.
|
|
76
|
+
#
|
|
77
|
+
# @param [Symbol] name The name for the paths group
|
|
78
|
+
# @param [Hash] opts An options hash
|
|
79
|
+
# @option opts [Boolean] :invert (false) inverts the order of the returned paths
|
|
80
|
+
#
|
|
81
|
+
# @example Read Directories:
|
|
82
|
+
# MyClass.dirs_for(:models)
|
|
83
|
+
#
|
|
84
|
+
# @example Inverted Read:
|
|
85
|
+
# MyClass.dirs_for(:models, :invert => true)
|
|
86
|
+
#
|
|
87
|
+
# @return [Array] An array of the paths
|
|
88
|
+
# Returned in declared order unless the :invert option is set
|
|
89
|
+
# @api public
|
|
90
|
+
# @since 0.1.1
|
|
91
|
+
# @author Daniel Neighman
|
|
92
|
+
def dirs_for(name, opts = {})
|
|
93
|
+
if _load_paths[name].blank?
|
|
94
|
+
[]
|
|
95
|
+
else
|
|
96
|
+
result = []
|
|
97
|
+
invert = !!opts[:invert]
|
|
98
|
+
load_paths = invert ? _load_paths[name].reverse : _load_paths[name]
|
|
99
|
+
roots.each do |root|
|
|
100
|
+
load_paths.each do |paths, glob|
|
|
101
|
+
paths = paths.reverse if invert
|
|
102
|
+
result << paths.map{|p| File.join(root, p)}
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
result.flatten
|
|
106
|
+
end # if
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Provides the list of paths (directories) and the associated globs for a given name.
|
|
110
|
+
#
|
|
111
|
+
# @param [Symbol] name The name of the path group
|
|
112
|
+
# @param [Hash] opts A hash of options
|
|
113
|
+
# @option opts [Boolean] :invert (false) Inverts the order of the paths
|
|
114
|
+
#
|
|
115
|
+
# @example
|
|
116
|
+
# MyClass.dirs_and_glob_for(:models)
|
|
117
|
+
#
|
|
118
|
+
# @return [Array] An array of [path, glob] arrays
|
|
119
|
+
# Returned in declared order unless the :invert option is set
|
|
120
|
+
# @api public
|
|
121
|
+
# @since 0.1.1
|
|
122
|
+
# @author Daniel Neighman
|
|
123
|
+
def dirs_and_glob_for(name, opts = {})
|
|
124
|
+
if _load_paths[name].blank?
|
|
125
|
+
[]
|
|
126
|
+
else
|
|
127
|
+
result = []
|
|
128
|
+
invert = !!opts[:invert]
|
|
129
|
+
load_paths = invert ? _load_paths[name].reverse : _load_paths[name]
|
|
130
|
+
roots.each do |root|
|
|
131
|
+
load_paths.each do |paths, glob|
|
|
132
|
+
paths = paths.reverse if invert
|
|
133
|
+
paths.each do |path|
|
|
134
|
+
result << [File.join(root, path), glob]
|
|
135
|
+
end # paths.each
|
|
136
|
+
end # load_paths.each
|
|
137
|
+
end # roots.each
|
|
138
|
+
result
|
|
139
|
+
end # if
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Provides an expanded, globbed list of paths and files for a given name.
|
|
143
|
+
#
|
|
144
|
+
# @param [Symbol] name The name of the paths group
|
|
145
|
+
# @param [Hash] opts An options hash
|
|
146
|
+
# @option opts [Boolean] :invert (false) Inverts the order of the returned values
|
|
147
|
+
#
|
|
148
|
+
# @example
|
|
149
|
+
# MyClass.paths_for(:model)
|
|
150
|
+
# MyClass.paths_for(:model, :invert => true)
|
|
151
|
+
#
|
|
152
|
+
# @return [Array]
|
|
153
|
+
# An array of [path, file] arrays. These may be joined to get the full path.
|
|
154
|
+
# All matched files for [paths, glob] will be returned in declared and then found order unless +:invert+ is true.
|
|
155
|
+
# Any path that has a +nil+ glob associated with it will be excluded.
|
|
156
|
+
#
|
|
157
|
+
# @api public
|
|
158
|
+
# @since 0.1.1
|
|
159
|
+
# @author Daniel Neighman
|
|
160
|
+
def paths_for(name, opts = {})
|
|
161
|
+
result = []
|
|
162
|
+
dirs_and_glob_for(name, opts).each do |path, glob|
|
|
163
|
+
next if glob.nil?
|
|
164
|
+
paths = Dir[File.join(path, glob)]
|
|
165
|
+
paths = paths.reverse if opts[:invert]
|
|
166
|
+
paths.each do |full_path|
|
|
167
|
+
result << [path, full_path.gsub(path, "")]
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
result
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Provides an expanded, globbed list of paths and files for a given name.
|
|
174
|
+
# The result includes only the last matched file of a given sub path and name.
|
|
175
|
+
#
|
|
176
|
+
# @param [Symbol] name The name of the paths group
|
|
177
|
+
# @param [Hash] opts An options hash
|
|
178
|
+
# @option opts [Boolean] :invert (false) Inverts the order of returned paths and files
|
|
179
|
+
#
|
|
180
|
+
# @example
|
|
181
|
+
# #Given the following:
|
|
182
|
+
# # /path/one/file1.rb
|
|
183
|
+
# # /path/one/file2.rb
|
|
184
|
+
# # /path/two/file1.rb
|
|
185
|
+
#
|
|
186
|
+
# MyClass.push_path(:files, ["/path/one", "/path/two"], "**/*.rb")
|
|
187
|
+
#
|
|
188
|
+
# MyClass.unique_paths_for(:files)
|
|
189
|
+
# MyClass.unique_paths_for(:files, :invert => true)
|
|
190
|
+
#
|
|
191
|
+
# @return [Array]
|
|
192
|
+
# Returns an array of [path, file] arrays
|
|
193
|
+
# Results are retuned in declared order. Only unique files are returned (the file part - the path)
|
|
194
|
+
# In the above example, the following would be returned for the standard call
|
|
195
|
+
# [
|
|
196
|
+
# ["#{root}/path/one", "/file2.rb"],
|
|
197
|
+
# ["#{root}/path/two", "/file1.rb"]
|
|
198
|
+
# ]
|
|
199
|
+
# For the inverted example the following is returned:
|
|
200
|
+
# [
|
|
201
|
+
# ["#{root}/path/one/file2.rb"],
|
|
202
|
+
# ["#{root}/path/one/file1.rb"]
|
|
203
|
+
# ]
|
|
204
|
+
#
|
|
205
|
+
# @api public
|
|
206
|
+
# @since 0.1.1
|
|
207
|
+
# @author Daniel Neighman
|
|
208
|
+
def unique_paths_for(name, opts = {})
|
|
209
|
+
tally = {}
|
|
210
|
+
output = []
|
|
211
|
+
paths_for(name, opts).reverse.each do |ary|
|
|
212
|
+
tally[ary[1]] ||= ary[0]
|
|
213
|
+
output << ary if tally[ary[1]] == ary[0]
|
|
214
|
+
end
|
|
215
|
+
output.reverse
|
|
216
|
+
end # unique_paths_for
|
|
217
|
+
end
|
|
218
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
module Pancake
|
|
2
|
+
# Get the ability to mark this as a consuming route.
|
|
3
|
+
class ::Usher::Route
|
|
4
|
+
attr_accessor :consuming
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
# Generate a url for any pancake configuration that has a router
|
|
8
|
+
#
|
|
9
|
+
# @example
|
|
10
|
+
# Pancake.url(UserManamgent, :login) # => "/users/login"
|
|
11
|
+
# @api public
|
|
12
|
+
def self.url(app_name, name_or_opts, opts = {})
|
|
13
|
+
config = Pancake.configuration.configs(app_name)
|
|
14
|
+
the_router = if config && config.router
|
|
15
|
+
config.router
|
|
16
|
+
elsif app_name.respond_to?(:router)
|
|
17
|
+
app_name.router
|
|
18
|
+
else
|
|
19
|
+
raise Pancake::Errors::UnknownRouter
|
|
20
|
+
end
|
|
21
|
+
the_router.url(name_or_opts, opts)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# The pancake router is a customized version of the Usher router.
|
|
25
|
+
# Usher is a fast tree based router that can generate routes, have
|
|
26
|
+
# nested routers, and even generate from nested routers.
|
|
27
|
+
# @see http://github.com/joshbuddy/usher
|
|
28
|
+
# @since 0.1.2
|
|
29
|
+
# @author Daniel Neighman
|
|
30
|
+
class Router < Usher::Interface::RackInterface
|
|
31
|
+
CONFIGURATION_KEY = "pancake.request.configuration".freeze
|
|
32
|
+
|
|
33
|
+
class RackApplicationExpected < ArgumentError; end
|
|
34
|
+
attr_accessor :configuration
|
|
35
|
+
|
|
36
|
+
# Mounts an application in the router as a sub application in the
|
|
37
|
+
# url space. This will route directly to the sub application and
|
|
38
|
+
# skip any middlewares etc.
|
|
39
|
+
def mount(mounted_app, path, options = {})
|
|
40
|
+
raise RackApplicationExpected unless mounted_app.respond_to?(:call)
|
|
41
|
+
exact_match = options.delete(:_exact)
|
|
42
|
+
route = add(path, options)
|
|
43
|
+
route.consuming = true
|
|
44
|
+
route.match_partially! unless exact_match
|
|
45
|
+
route.to(mounted_app)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Adds a route to the router.
|
|
49
|
+
# @see Usher::Interface::RackInterface#add
|
|
50
|
+
def add(path, opts = {}, &block)
|
|
51
|
+
opts = cooerce_options_to_usher(opts)
|
|
52
|
+
route = super(path, opts)
|
|
53
|
+
if block_given?
|
|
54
|
+
route.to(block)
|
|
55
|
+
end
|
|
56
|
+
route
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Generate a url
|
|
60
|
+
def url(name_or_path, options = {})
|
|
61
|
+
if Hash === name_or_path
|
|
62
|
+
name = nil
|
|
63
|
+
options = name_or_path
|
|
64
|
+
else
|
|
65
|
+
name = name_or_path
|
|
66
|
+
end
|
|
67
|
+
generate(name, options)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def call(env)
|
|
71
|
+
orig_config = env[CONFIGURATION_KEY]
|
|
72
|
+
env[CONFIGURATION_KEY] = configuration
|
|
73
|
+
super(env)
|
|
74
|
+
ensure
|
|
75
|
+
env[CONFIGURATION_KEY] = orig_config
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
# Canoodles the options into a format that usher is happy to
|
|
80
|
+
# accept. This is so that we can have a different interface from
|
|
81
|
+
# the raw usher when we're first declaring the route.
|
|
82
|
+
# @api private
|
|
83
|
+
def cooerce_options_to_usher(opts)
|
|
84
|
+
defaults = opts.delete(:_defaults)
|
|
85
|
+
opts[:default_values] ||= {}
|
|
86
|
+
opts[:default_values].merge!(defaults) if defaults
|
|
87
|
+
opts
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Overwrites the method in Rack::Interface::RackInterface to mash
|
|
91
|
+
# the usher.params into the rack request.params
|
|
92
|
+
# @api private
|
|
93
|
+
def after_match(request, response)
|
|
94
|
+
super
|
|
95
|
+
consume_path!(request, response) if !response.partial_match? && response.path.route.consuming
|
|
96
|
+
request.params.merge!(request.env['usher.params']) unless request.env['usher.params'].empty?
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
module Pancake
|
|
2
|
+
class Stack
|
|
3
|
+
inheritable_inner_classes :BootLoader
|
|
4
|
+
|
|
5
|
+
# The default bootloader is where the stack default bootloaders are stored
|
|
6
|
+
# These are shared across all bootloaders
|
|
7
|
+
class BootLoader # :nodoc:
|
|
8
|
+
extend ::Pancake::BootLoaderMixin
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
end # Stack
|
|
12
|
+
end # Pancake
|
|
13
|
+
|
|
14
|
+
#################### Define the bootloaders here #############################
|
|
15
|
+
# :level => :init bootloaders only have the stack class available
|
|
16
|
+
# They do not have :stack available
|
|
17
|
+
# These are not run directly, but are run from inherited stacks
|
|
18
|
+
Pancake::Stack::BootLoader.add(:mount_applications, :level => :init) do
|
|
19
|
+
def run!
|
|
20
|
+
# Mount any stacks this stack may have in it.
|
|
21
|
+
stack_class.roots.each do |root|
|
|
22
|
+
Dir["#{root}/mounts/*/pancake.init"].each{|f| load f if File.exists?(f)}
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
Pancake::Stack::BootLoader.add(:load_configuration, :level => :init) do
|
|
28
|
+
def run!
|
|
29
|
+
stack_class.roots.each do |root|
|
|
30
|
+
stack_class.paths_for(:config).each{|f| require f.join}
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
Pancake::Stack::BootLoader.add(:load_application, :level => :init) do
|
|
36
|
+
def run!
|
|
37
|
+
stack_class.roots.each do |root|
|
|
38
|
+
[:models, :controllers].each do |type|
|
|
39
|
+
stack_class.paths_for(type).each{|f| require f.join}
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
Pancake::Stack::BootLoader.add(:load_routes, :level => :init) do
|
|
46
|
+
def run!
|
|
47
|
+
stack_class.roots.each do |root|
|
|
48
|
+
stack_class.paths_for(:router).each{|f| require f.join}
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
###### -================== Stack Building BootLoaders
|
|
54
|
+
# Pancake stacks need to be built with the following options
|
|
55
|
+
# MyApp::BootLoader.run!({
|
|
56
|
+
# :stack_class => self.class,
|
|
57
|
+
# :stack => self,
|
|
58
|
+
# :app => app,
|
|
59
|
+
# :app_name => app_name,
|
|
60
|
+
# })
|
|
61
|
+
#
|
|
62
|
+
#
|
|
63
|
+
|
|
64
|
+
Pancake::Stack::BootLoader.add(:initialize_application) do
|
|
65
|
+
def run!
|
|
66
|
+
config[:app] ||= stack_class.new_app_instance
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
Pancake::Stack::BootLoader.add(:build_stack) do
|
|
71
|
+
def run!
|
|
72
|
+
mwares = stack_class.middlewares(Pancake.stack_labels)
|
|
73
|
+
app = Pancake::Middleware.build(config[:app], mwares)
|
|
74
|
+
app_config = Pancake.configuration.configs(config[:app_name])
|
|
75
|
+
app_config.app = app
|
|
76
|
+
app_config.stack = stack_class
|
|
77
|
+
app_config.router.configuration = app_config
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Pancake
|
|
2
|
+
class Stack
|
|
3
|
+
|
|
4
|
+
class Configuration < Pancake::Configuration::Base
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
# Provides access to the configuration block for the stack.
|
|
8
|
+
# If a block is provided, it opens the specific configuration instances anonymous class
|
|
9
|
+
# and allows you to edit it.
|
|
10
|
+
# If no block is provided, it just returns the configuration object.
|
|
11
|
+
#
|
|
12
|
+
# :api: public
|
|
13
|
+
def self.configuration(label = self, &block)
|
|
14
|
+
config = Pancake.configuration.configs[label] ||= self::Configuration.new
|
|
15
|
+
config.class.class_eval(&block) if block
|
|
16
|
+
config
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def configuration(label = self.class)
|
|
20
|
+
yield self.class.configuration(label) if block_given?
|
|
21
|
+
self.class.configuration(label)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end # Stack
|
|
25
|
+
end # Pancake
|
|
26
|
+
|
|
27
|
+
####################
|
|
28
|
+
# Setup the default configuration for each stack
|
|
29
|
+
class Pancake::Stack::Configuration
|
|
30
|
+
default :router, lambda{ _router }, "The router for this stack"
|
|
31
|
+
|
|
32
|
+
def _router
|
|
33
|
+
@_router ||= begin
|
|
34
|
+
unless stack.nil?
|
|
35
|
+
r = stack.router.dup
|
|
36
|
+
r.configuration = self
|
|
37
|
+
r.app = app
|
|
38
|
+
r.configuration = self
|
|
39
|
+
r
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|