orange-core 0.5.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +145 -0
- data/lib/orange-core.rb +8 -0
- data/lib/orange-core/application.rb +132 -0
- data/lib/orange-core/assets/css/exceptions.css +50 -0
- data/lib/orange-core/assets/js/exceptions.js +44 -0
- data/lib/orange-core/carton.rb +178 -0
- data/lib/orange-core/core.rb +266 -0
- data/lib/orange-core/magick.rb +270 -0
- data/lib/orange-core/middleware/base.rb +96 -0
- data/lib/orange-core/middleware/database.rb +45 -0
- data/lib/orange-core/middleware/four_oh_four.rb +45 -0
- data/lib/orange-core/middleware/globals.rb +17 -0
- data/lib/orange-core/middleware/loader.rb +13 -0
- data/lib/orange-core/middleware/rerouter.rb +53 -0
- data/lib/orange-core/middleware/restful_router.rb +99 -0
- data/lib/orange-core/middleware/route_context.rb +39 -0
- data/lib/orange-core/middleware/route_site.rb +51 -0
- data/lib/orange-core/middleware/show_exceptions.rb +80 -0
- data/lib/orange-core/middleware/static.rb +67 -0
- data/lib/orange-core/middleware/static_file.rb +32 -0
- data/lib/orange-core/middleware/template.rb +60 -0
- data/lib/orange-core/packet.rb +232 -0
- data/lib/orange-core/plugin.rb +172 -0
- data/lib/orange-core/resource.rb +96 -0
- data/lib/orange-core/resources/mapper.rb +36 -0
- data/lib/orange-core/resources/model_resource.rb +228 -0
- data/lib/orange-core/resources/not_found.rb +10 -0
- data/lib/orange-core/resources/page_parts.rb +68 -0
- data/lib/orange-core/resources/parser.rb +113 -0
- data/lib/orange-core/resources/routable_resource.rb +16 -0
- data/lib/orange-core/resources/scaffold.rb +106 -0
- data/lib/orange-core/stack.rb +226 -0
- data/lib/orange-core/templates/exceptions.haml +111 -0
- data/lib/orange-core/views/default_resource/create.haml +4 -0
- data/lib/orange-core/views/default_resource/edit.haml +9 -0
- data/lib/orange-core/views/default_resource/list.haml +10 -0
- data/lib/orange-core/views/default_resource/show.haml +4 -0
- data/lib/orange-core/views/default_resource/table_row.haml +7 -0
- data/lib/orange-core/views/not_found/404.haml +2 -0
- data/spec/orange-core/application_spec.rb +183 -0
- data/spec/orange-core/carton_spec.rb +136 -0
- data/spec/orange-core/core_spec.rb +248 -0
- data/spec/orange-core/magick_spec.rb +96 -0
- data/spec/orange-core/middleware/base_spec.rb +38 -0
- data/spec/orange-core/middleware/globals_spec.rb +3 -0
- data/spec/orange-core/middleware/rerouter_spec.rb +3 -0
- data/spec/orange-core/middleware/restful_router_spec.rb +3 -0
- data/spec/orange-core/middleware/route_context_spec.rb +3 -0
- data/spec/orange-core/middleware/route_site_spec.rb +3 -0
- data/spec/orange-core/middleware/show_exceptions_spec.rb +3 -0
- data/spec/orange-core/middleware/static_file_spec.rb +3 -0
- data/spec/orange-core/middleware/static_spec.rb +3 -0
- data/spec/orange-core/mock/mock_app.rb +16 -0
- data/spec/orange-core/mock/mock_carton.rb +43 -0
- data/spec/orange-core/mock/mock_core.rb +2 -0
- data/spec/orange-core/mock/mock_middleware.rb +25 -0
- data/spec/orange-core/mock/mock_mixins.rb +19 -0
- data/spec/orange-core/mock/mock_model_resource.rb +47 -0
- data/spec/orange-core/mock/mock_pulp.rb +24 -0
- data/spec/orange-core/mock/mock_resource.rb +26 -0
- data/spec/orange-core/mock/mock_router.rb +10 -0
- data/spec/orange-core/orange_spec.rb +19 -0
- data/spec/orange-core/packet_spec.rb +203 -0
- data/spec/orange-core/resource_spec.rb +96 -0
- data/spec/orange-core/resources/mapper_spec.rb +5 -0
- data/spec/orange-core/resources/model_resource_spec.rb +246 -0
- data/spec/orange-core/resources/parser_spec.rb +5 -0
- data/spec/orange-core/resources/routable_resource_spec.rb +5 -0
- data/spec/orange-core/spec_helper.rb +53 -0
- data/spec/orange-core/stack_spec.rb +232 -0
- data/spec/stats.rb +182 -0
- metadata +227 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'orange-core/resource'
|
2
|
+
module Orange
|
3
|
+
class PageParts < Resource
|
4
|
+
def afterLoad
|
5
|
+
orange.add_pulp Orange::Pulp::PageParts
|
6
|
+
end
|
7
|
+
|
8
|
+
def part(packet)
|
9
|
+
unless packet[:page_parts, false]
|
10
|
+
packet[:page_parts] = DefaultHash.new
|
11
|
+
packet[:page_parts].default = ''
|
12
|
+
end
|
13
|
+
packet[:page_parts]
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def add_css(packet, file, opts = {})
|
18
|
+
ie = opts[:ie] || false
|
19
|
+
mod = opts[:module] || 'public'
|
20
|
+
# module set to false gives the root assets dir
|
21
|
+
assets = File.join('assets', mod)
|
22
|
+
file = File.join('', assets, 'css', file)
|
23
|
+
unless packet[:css_files, []].include?(file)
|
24
|
+
if ie
|
25
|
+
part(packet)[:ie_css] = part(packet)[:ie_css] + "<link rel=\"stylesheet\" href=\"#{file}\" type=\"text/css\" media=\"screen\" charset=\"utf-8\" />"
|
26
|
+
else
|
27
|
+
part(packet)[:css] = part(packet)[:css] + "<link rel=\"stylesheet\" href=\"#{file}\" type=\"text/css\" media=\"screen\" charset=\"utf-8\" />"
|
28
|
+
end
|
29
|
+
packet[:css_files] ||= []
|
30
|
+
packet[:css_files].insert((opts[:position] ? opts[:position] : -1), file)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def add_js(packet, file, opts = {})
|
35
|
+
ie = opts[:ie] || false
|
36
|
+
mod = opts[:module] || 'public'
|
37
|
+
assets = File.join('assets', mod)
|
38
|
+
file = File.join('', assets, 'js', file)
|
39
|
+
unless packet[:js_files, []].include?(file)
|
40
|
+
if ie
|
41
|
+
part(packet)[:ie_js] = part(packet)[:ie_js] + "<script src=\"#{file}\" type=\"text/javascript\"></script>"
|
42
|
+
else
|
43
|
+
part(packet)[:js] = part(packet)[:js] + "<script src=\"#{file}\" type=\"text/javascript\"></script>"
|
44
|
+
end
|
45
|
+
packet[:js_files] ||= []
|
46
|
+
packet[:js_files].insert((opts[:position] ? opts[:position] : -1), file)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
module Pulp::PageParts
|
52
|
+
def part
|
53
|
+
orange[:page_parts].part(packet)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Feels like part should be plural, no?
|
57
|
+
def parts; part; end
|
58
|
+
|
59
|
+
|
60
|
+
def add_css(file, opts = {})
|
61
|
+
orange[:page_parts].add_css(packet, file, opts)
|
62
|
+
end
|
63
|
+
|
64
|
+
def add_js(file, opts = {})
|
65
|
+
orange[:page_parts].add_js(packet, file, opts)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'orange-core/core'
|
2
|
+
require 'haml'
|
3
|
+
require 'yaml'
|
4
|
+
require 'crack'
|
5
|
+
|
6
|
+
module Orange
|
7
|
+
class Parser < Resource
|
8
|
+
def afterLoad
|
9
|
+
orange.add_pulp Orange::Pulp::ParserPulp
|
10
|
+
@template_dirs = [File.join(orange.core_dir, 'templates')]
|
11
|
+
@view_dirs = [File.join(orange.core_dir, 'views')]
|
12
|
+
Orange.plugins.each{|p| @template_dirs << p.templates if p.has_templates? }
|
13
|
+
Orange.plugins.each{|p| @view_dirs << p.views if p.has_views? }
|
14
|
+
end
|
15
|
+
|
16
|
+
def yaml(file)
|
17
|
+
return nil unless File.exists?(file)
|
18
|
+
string = File.read(file)
|
19
|
+
string.gsub!('__ORANGE__', orange.app_dir)
|
20
|
+
out = YAML::load(string)
|
21
|
+
end
|
22
|
+
|
23
|
+
def haml(file, packet_binding, *vars, &block)
|
24
|
+
|
25
|
+
opts = vars.extract_options!
|
26
|
+
# Initial info
|
27
|
+
temp = opts.delete(:template)
|
28
|
+
opts[:resource_name] = opts[:resource].orange_name.to_s if
|
29
|
+
opts[:resource] && opts[:resource].respond_to?(:orange_name)
|
30
|
+
resource = (opts[:resource_name] || '').downcase
|
31
|
+
|
32
|
+
if packet_binding.is_a? Orange::Packet
|
33
|
+
context = packet_binding['route.context'].to_s
|
34
|
+
unless temp
|
35
|
+
packet_binding['parser.haml-templates'] ||= {}
|
36
|
+
haml_engine = packet_binding['parser.haml-templates']["#{context}-#{resource}-#{file}"] || false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
unless haml_engine
|
40
|
+
opts.merge :orange => orange
|
41
|
+
|
42
|
+
string = false
|
43
|
+
if temp
|
44
|
+
string ||= read_if_exists('templates', file)
|
45
|
+
@template_dirs.each do |templates_dir|
|
46
|
+
string ||= read_if_exists(templates_dir, file)
|
47
|
+
end unless string
|
48
|
+
end
|
49
|
+
|
50
|
+
if context
|
51
|
+
#Check for context specific overrides
|
52
|
+
string ||= read_if_exists('views', resource, context+"."+file) if resource
|
53
|
+
string ||= read_if_exists('views', context+"."+file)
|
54
|
+
@view_dirs.each do |views_dir|
|
55
|
+
string ||= read_if_exists(views_dir, resource, context+"."+file) if resource
|
56
|
+
string ||= read_if_exists(views_dir, context+"."+file)
|
57
|
+
end unless string
|
58
|
+
end
|
59
|
+
|
60
|
+
# Check for standard views
|
61
|
+
string ||= read_if_exists('views', resource, file) if resource
|
62
|
+
string ||= read_if_exists('views', file)
|
63
|
+
@view_dirs.each do |views_dir|
|
64
|
+
string ||= read_if_exists(views_dir, resource, file) if resource
|
65
|
+
string ||= read_if_exists(views_dir, file)
|
66
|
+
end unless string
|
67
|
+
|
68
|
+
# Check for default resource views
|
69
|
+
string ||= read_if_exists('views', 'default_resource', file)
|
70
|
+
@view_dirs.each do |views_dir|
|
71
|
+
string ||= read_if_exists(views_dir, 'default_resource', file) if resource
|
72
|
+
end unless string
|
73
|
+
raise LoadError, "Couldn't find haml file '#{file}'" unless string
|
74
|
+
|
75
|
+
haml_engine = Haml::Engine.new(string)
|
76
|
+
if packet_binding.is_a? Orange::Packet
|
77
|
+
packet_binding['parser.haml-templates']["#{context}-#{resource}-#{file}"] = haml_engine
|
78
|
+
end
|
79
|
+
end
|
80
|
+
out = haml_engine.render(packet_binding, opts, &block)
|
81
|
+
end
|
82
|
+
|
83
|
+
def read_if_exists(*args)
|
84
|
+
return File.read(File.join(*args)) if File.exists?(File.join(*args))
|
85
|
+
false
|
86
|
+
end
|
87
|
+
|
88
|
+
def hpricot(text)
|
89
|
+
require 'hpricot'
|
90
|
+
Hpricot(text)
|
91
|
+
end
|
92
|
+
|
93
|
+
def xml(text)
|
94
|
+
Crack::XML.parse(text)
|
95
|
+
end
|
96
|
+
|
97
|
+
def json(text)
|
98
|
+
Crack::JSON.parse(text)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
module Pulp::ParserPulp
|
103
|
+
def html(&block)
|
104
|
+
if block_given?
|
105
|
+
unless(packet[:content].blank?)
|
106
|
+
doc = orange[:parser].hpricot(packet[:content])
|
107
|
+
yield doc
|
108
|
+
packet[:content] = doc.to_s
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'orange-core/resource'
|
2
|
+
|
3
|
+
module Orange
|
4
|
+
class RoutableResource < Resource
|
5
|
+
def routable; true; end
|
6
|
+
|
7
|
+
def route(path, packet)
|
8
|
+
parts = path.split('/')
|
9
|
+
first = parts[0].respond_to?(:to_sym) ? parts.shift.to_sym : :index
|
10
|
+
new_path = parts.join('/')
|
11
|
+
if self.respond_to?(first)
|
12
|
+
packet[:content] = self.__send__(first, new_path, packet)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'orange-core/core'
|
2
|
+
|
3
|
+
module Orange
|
4
|
+
class Scaffold < Resource
|
5
|
+
# Load the scaffold helpers
|
6
|
+
def afterLoad
|
7
|
+
orange.add_pulp Pulp::ScaffoldHelpers
|
8
|
+
Packet.meta_methods(/view_([a-zA-Z_]+)/) do |packet, match, args|
|
9
|
+
model = args.shift
|
10
|
+
args = args.extract_with_defaults(:mode => match[1].to_sym)
|
11
|
+
packet.view(model, args)
|
12
|
+
end
|
13
|
+
@scaffold_types = {}
|
14
|
+
add_scaffold_type(:boolean) do |name, val, opts|
|
15
|
+
if opts[:show]
|
16
|
+
val ? "true" : "false"
|
17
|
+
else
|
18
|
+
ret = "<input type='hidden' name='#{opts[:model_name]}[#{name}]' value='0' /><input type='checkbox' name='#{opts[:model_name]}[#{name}]' value='1' #{'checked="checked"' if (val && val != '')}/>"
|
19
|
+
ret = "<label for=''>#{opts[:display_name]}</label><br />" + ret if opts[:label]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def add_scaffold_type(type, &block)
|
25
|
+
@scaffold_types[type] = Proc.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def scaffold_attribute(packet, prop, model_name, *args)
|
29
|
+
args = args.extract_options!
|
30
|
+
args.with_defaults!({:packet => packet, :value => '', :label => false, :show => false})
|
31
|
+
val = args[:value]
|
32
|
+
label = args[:label]
|
33
|
+
show = args[:show]
|
34
|
+
name = prop[:name]
|
35
|
+
human_readable_name = name.to_s.split('_').each{|w| w.capitalize!}.join(' ')
|
36
|
+
display_name = prop[:display_name] || human_readable_name
|
37
|
+
return @scaffold_types[prop[:type]].call(name, val, args.with_defaults!(:display_name => display_name, :model_name => model_name)) if @scaffold_types.has_key?(prop[:type])
|
38
|
+
unless show
|
39
|
+
case prop[:type]
|
40
|
+
when :title
|
41
|
+
val.gsub!('"', '"')
|
42
|
+
ret = "<input class=\"title\" type=\"text\" value=\"#{val}\" name=\"#{model_name}[#{name}]\" />"
|
43
|
+
when :text
|
44
|
+
val.gsub!('"', '"')
|
45
|
+
ret = "<input type=\"text\" value=\"#{val}\" name=\"#{model_name}[#{name}]\" />"
|
46
|
+
when :fulltext
|
47
|
+
ret = "<textarea name='#{model_name}[#{name}]'>#{val}</textarea>"
|
48
|
+
when :boolean
|
49
|
+
human_readable_name = human_readable_name + '?'
|
50
|
+
ret = "<input type='hidden' name='#{model_name}[#{name}]' value='0' /><input type='checkbox' name='#{model_name}[#{name}]' value='1' #{'checked="checked"' if (val && val != '')}/>"
|
51
|
+
when :date
|
52
|
+
val.gsub!('"', '"')
|
53
|
+
ret = "<input class=\"date\" type=\"text\" value=\"#{val}\" name=\"#{model_name}[#{name}]\" />"
|
54
|
+
else
|
55
|
+
val.gsub!('"', '"')
|
56
|
+
ret = "<input type=\"text\" value=\"#{val}\" name=\"#{model_name}[#{name}]\" />"
|
57
|
+
end
|
58
|
+
ret = "<label for=''>#{display_name}</label><br />" + ret if label
|
59
|
+
else
|
60
|
+
case prop[:type]
|
61
|
+
when :title
|
62
|
+
ret = "<h3 class='#{model_name}-#{name}'>#{val}</h3>"
|
63
|
+
when :text
|
64
|
+
ret = "<p class='#{model_name}-#{name}'>#{val}</p>"
|
65
|
+
when :fulltext
|
66
|
+
ret = "<div class='#{model_name}-#{name}'>#{val}</div>"
|
67
|
+
else
|
68
|
+
ret = "<div class='#{model_name}-#{name}'>#{val}</div>"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
return ret
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
module Pulp::ScaffoldHelpers
|
76
|
+
# Creates a button that appears to be a link but
|
77
|
+
# does form submission with custom method (_method param in POST)
|
78
|
+
# This is to avoid issues of a destructive get.
|
79
|
+
# @param [String] text link text to show
|
80
|
+
# @param [String] link the actual href value of the link
|
81
|
+
# @param [String, false] confirm text of the javascript confirm (false for none [default])
|
82
|
+
# @param [optional, Array] args array of optional arguments, only opts[:method] defined
|
83
|
+
# @option opts [String] method method name (Should be 'DELETE', 'PUT' or 'POST')
|
84
|
+
def form_link(text, link, confirm = false, opts = {})
|
85
|
+
text = "<img src='#{opts[:img]}' alt='#{text}' />" if opts[:img]
|
86
|
+
css = opts[:class]? opts[:class] : 'form_button_link'
|
87
|
+
meth = (opts[:method]? "<input type='hidden' name='_method' value='#{opts[:method]}' />" : '')
|
88
|
+
if confirm
|
89
|
+
"<form action='#{link}' method='post' class='mini' onsubmit='return confirm(\"#{confirm}\")'><button class='link_button'><a href='#' class='#{css}'>#{text}</a></button>#{meth}</form>"
|
90
|
+
else
|
91
|
+
"<form action='#{link}' method='post' class='mini'><button class='link_button'><a href='#' class='#{css}'>#{text}</a></button>#{meth}</form>"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Calls view for an orange resource.
|
96
|
+
def view(model_name, *args)
|
97
|
+
orange[model_name].view(self, *args)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Returns a scaffolded attribute
|
101
|
+
def view_attribute(prop, model_name, *args)
|
102
|
+
orange[:scaffold].scaffold_attribute(self, prop, model_name, *args)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
@@ -0,0 +1,226 @@
|
|
1
|
+
require 'orange-core/core'
|
2
|
+
require 'rack/builder'
|
3
|
+
module Orange
|
4
|
+
# Builds an orange stack of middleware
|
5
|
+
# Use in the rackup file as follows:
|
6
|
+
# app = Orange::Stack.new do
|
7
|
+
# stack Orange::DataMapper 'sqlite3::memory:' <= loads orange specific middleware
|
8
|
+
# use OtherMiddleware
|
9
|
+
# run SomeApp.new
|
10
|
+
# end
|
11
|
+
# run app
|
12
|
+
#
|
13
|
+
# All middleware placed inside the Orange::Stack will have access
|
14
|
+
# to the Orange Core (as long as it's been written to accept it as the second
|
15
|
+
# initialization argument) when added with the 'stack' method
|
16
|
+
#
|
17
|
+
# In general, Orange::Stack works like Rack::Builder.
|
18
|
+
class Stack
|
19
|
+
|
20
|
+
# Creates a new Orange::Stack out of the passed block.
|
21
|
+
#
|
22
|
+
# If a block is not passed, it will try to build one from scratch.
|
23
|
+
# The bare minimum will be `run app_class.new(@core)`, there are also
|
24
|
+
# other stacks that can be used.
|
25
|
+
#
|
26
|
+
# @param [Orange::Application] app_class the class of the main application
|
27
|
+
# @param [Orange::Core] core the orange core
|
28
|
+
# @param [Symbol] prebuilt the optional prebuilt stack, if one isn't passed as block
|
29
|
+
def initialize(app_class = nil, core = false, prebuilt = :none, &block)
|
30
|
+
@build = Rack::Builder.new
|
31
|
+
@core = core || Orange::Core.new
|
32
|
+
@core.stack = self # Set a back reference in the core.
|
33
|
+
@auto_reload = false
|
34
|
+
@app = false
|
35
|
+
@middleware = []
|
36
|
+
@recapture = true
|
37
|
+
@main_app = app_class
|
38
|
+
if block_given?
|
39
|
+
instance_eval(&block)
|
40
|
+
else
|
41
|
+
@main_app = app_class.new(@core) unless app_class.nil?
|
42
|
+
prebuild(prebuilt)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Runs methods necessary to build a stack. Don't use if a stack
|
47
|
+
# has already been built by the initialize block.
|
48
|
+
#
|
49
|
+
# @todo Offer more choices for default stacks
|
50
|
+
def prebuild(choice)
|
51
|
+
case choice
|
52
|
+
when :none
|
53
|
+
run @main_app
|
54
|
+
else
|
55
|
+
run @main_app
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns the main application instance that was added by the
|
60
|
+
# run method. Obviously won't return anything useful if the
|
61
|
+
# middleware stack hasn't been set up with an explicit exit point,
|
62
|
+
# as could be the case for a pure orange middleware stack on
|
63
|
+
# top of a different exit application (like Sinatra or Rails)
|
64
|
+
def main_app
|
65
|
+
@main_app
|
66
|
+
end
|
67
|
+
|
68
|
+
# Adds middleware using the Rack::Builder#use method
|
69
|
+
# @param [Object] middleware A class of middleware that meets rack middleware requirements
|
70
|
+
def use(middleware, *args, &block)
|
71
|
+
@build.use(middleware, *args, &block)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Loads resources into the core using the Orange::Core#load method
|
75
|
+
#
|
76
|
+
# all args are passed on
|
77
|
+
def load(*args, &block)
|
78
|
+
orange.load(*args, &block)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Adds Orange-aware middleware using the Rack::Builder#use method, adding
|
82
|
+
# the orange core to the args passed on
|
83
|
+
def stack(middleware, *args, &block)
|
84
|
+
@build.use(middleware, @core, *args, &block)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Set the auto_reload option, called without args, defaults to true,
|
88
|
+
# other option is to set it to false
|
89
|
+
def auto_reload!(val = true)
|
90
|
+
@auto_reload = val
|
91
|
+
end
|
92
|
+
|
93
|
+
# Shortcut for adding Orange::Middleware::ShowExceptions to the middleware
|
94
|
+
# stack
|
95
|
+
def use_exceptions
|
96
|
+
stack Orange::Middleware::ShowExceptions
|
97
|
+
end
|
98
|
+
|
99
|
+
# Alias for use_exceptions
|
100
|
+
def show_exceptions
|
101
|
+
use_exceptions
|
102
|
+
end
|
103
|
+
|
104
|
+
# Turn off recapture middleware, which is normally just on top of the exit
|
105
|
+
# point
|
106
|
+
# @see Orange::Middleware::Recapture
|
107
|
+
def no_recapture
|
108
|
+
@recapture = false
|
109
|
+
end
|
110
|
+
|
111
|
+
# A shortcut for adding many of the routing middleware options
|
112
|
+
# simultaneously. Includes:
|
113
|
+
# * Orange::Middleware::Rerouter
|
114
|
+
# * Orange::Middleware::Static
|
115
|
+
# * Rack::AbstractFormat
|
116
|
+
# * Orange::Middleware::RouteSite
|
117
|
+
# * Orange::Middleware::RouteContext
|
118
|
+
#
|
119
|
+
# All of these are passed the args hash to use as they will, except
|
120
|
+
# for Rack::AbstractFormat
|
121
|
+
#
|
122
|
+
def prerouting(*args)
|
123
|
+
opts = args.extract_options!
|
124
|
+
stack Orange::Middleware::Globals
|
125
|
+
stack Orange::Middleware::Loader
|
126
|
+
stack Orange::Middleware::Rerouter, opts.dup
|
127
|
+
stack Orange::Middleware::Static, opts.dup
|
128
|
+
use Rack::AbstractFormat unless opts[:no_abstract_format]
|
129
|
+
# Must be used before non-destructive route altering done by Orange,
|
130
|
+
# since all orange stuff is non-destructive
|
131
|
+
stack Orange::Middleware::RouteSite, opts.dup
|
132
|
+
stack Orange::Middleware::RouteContext, opts.dup
|
133
|
+
stack Orange::Middleware::Database
|
134
|
+
Orange.plugins.each{|p| p.middleware(:prerouting).each{|m| stack m, opts.dup} if p.has_middleware?}
|
135
|
+
end
|
136
|
+
|
137
|
+
# A shortcut for routing via Orange::Middleware::RestfulRouter and any plugins
|
138
|
+
#
|
139
|
+
# Any args are passed on to the middleware
|
140
|
+
def routing(opts ={})
|
141
|
+
stack Orange::Middleware::RestfulRouter, opts.dup
|
142
|
+
Orange.plugins.each{|p| p.middleware(:routing).each{|m| stack m, opts.dup} if p.has_middleware?}
|
143
|
+
end
|
144
|
+
|
145
|
+
def postrouting(opts ={})
|
146
|
+
Orange.plugins.each{|p| p.middleware(:postrouting).each{|m| stack m, opts.dup} if p.has_middleware?}
|
147
|
+
stack Orange::Middleware::Template
|
148
|
+
stack Orange::Middleware::FourOhFour, opts.dup # Last ditch, send route to 404 page.
|
149
|
+
end
|
150
|
+
|
151
|
+
def responders(opts ={})
|
152
|
+
Orange.plugins.each{|p| p.middleware(:responders).each{|m| stack m, opts.dup} if p.has_middleware?}
|
153
|
+
end
|
154
|
+
|
155
|
+
# # A shortcut to enable Rack::OpenID and Orange::Middleware::AccessControl
|
156
|
+
# #
|
157
|
+
# # Args will be passed on to Orange::Middleware::AccessControl
|
158
|
+
# def openid_access_control(*args)
|
159
|
+
# opts = args.extract_options!
|
160
|
+
#
|
161
|
+
# end
|
162
|
+
|
163
|
+
# Adds pulp to the core via the Orange::Core#add_pulp method
|
164
|
+
# @param [Orange::Mixin] mod a mixin to be included in the packet
|
165
|
+
def add_pulp(mod)
|
166
|
+
orange.add_pulp(mod)
|
167
|
+
end
|
168
|
+
|
169
|
+
# The exit point for the middleware stack,
|
170
|
+
# add the app to @main_app and then call Rack::Builder#run with the main app
|
171
|
+
def run(app, *args)
|
172
|
+
opts = args.extract_options!
|
173
|
+
@main_app = app
|
174
|
+
@build.run(app)
|
175
|
+
end
|
176
|
+
|
177
|
+
# Returns the Orange::Core
|
178
|
+
# @return [Orange::Core] The orange core
|
179
|
+
def orange
|
180
|
+
@core
|
181
|
+
end
|
182
|
+
|
183
|
+
# Passes through to Rack::Builder#map
|
184
|
+
# @todo Make this work - passing the block on to builder
|
185
|
+
# means we can't intercept anything, which will yield
|
186
|
+
# unexpected results
|
187
|
+
def map(path, &block)
|
188
|
+
raise 'not yet supported'
|
189
|
+
@build.map(path, &block)
|
190
|
+
end
|
191
|
+
|
192
|
+
# Builds the middleware stack (or uses a cached one)
|
193
|
+
#
|
194
|
+
# If auto_reload is enabled ({#auto_reload!}), builds every time
|
195
|
+
#
|
196
|
+
# @return [Object] a full stack of middleware and the exit application,
|
197
|
+
# conforming to Rack guidelines
|
198
|
+
def app
|
199
|
+
if @auto_reload
|
200
|
+
orange.fire(:stack_reloading, @app) if orange.stack # Alert we are rebuilding
|
201
|
+
@app = false # Rebuild no matter what if autoload
|
202
|
+
end
|
203
|
+
unless @app
|
204
|
+
@app = do_build # Build if necessary
|
205
|
+
orange.fire(:stack_loaded, @app)
|
206
|
+
end
|
207
|
+
@app
|
208
|
+
end
|
209
|
+
|
210
|
+
def do_build
|
211
|
+
@build.to_app
|
212
|
+
end
|
213
|
+
|
214
|
+
# Sets the core and then passes on to the stack, according to standard
|
215
|
+
# rack procedure
|
216
|
+
def call(env)
|
217
|
+
env['orange.core'] = @core
|
218
|
+
app.call(env)
|
219
|
+
end
|
220
|
+
|
221
|
+
# Debug helping
|
222
|
+
def inspect
|
223
|
+
"#<Orange::Stack:0x#{self.object_id.to_s(16)} @build=#{@build.inspect}, @core=#{@core.inspect}>"
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|