raw 0.49.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.
- data/doc/CONTRIBUTORS +106 -0
- data/doc/LICENSE +32 -0
- data/doc/coding_conventions.txt +11 -0
- data/lib/raw.rb +42 -0
- data/lib/raw/adapter.rb +113 -0
- data/lib/raw/adapter/cgi.rb +41 -0
- data/lib/raw/adapter/fastcgi.rb +48 -0
- data/lib/raw/adapter/mongrel.rb +146 -0
- data/lib/raw/adapter/script.rb +94 -0
- data/lib/raw/adapter/webrick.rb +144 -0
- data/lib/raw/adapter/webrick/vcr.rb +91 -0
- data/lib/raw/cgi.rb +323 -0
- data/lib/raw/cgi/cookie.rb +47 -0
- data/lib/raw/cgi/http.rb +62 -0
- data/lib/raw/compiler.rb +138 -0
- data/lib/raw/compiler/filter/cleanup.rb +21 -0
- data/lib/raw/compiler/filter/elements.rb +166 -0
- data/lib/raw/compiler/filter/elements/element.rb +210 -0
- data/lib/raw/compiler/filter/localization.rb +23 -0
- data/lib/raw/compiler/filter/markup.rb +32 -0
- data/lib/raw/compiler/filter/morph.rb +123 -0
- data/lib/raw/compiler/filter/morph/each.rb +34 -0
- data/lib/raw/compiler/filter/morph/for.rb +11 -0
- data/lib/raw/compiler/filter/morph/if.rb +26 -0
- data/lib/raw/compiler/filter/morph/selected_if.rb +43 -0
- data/lib/raw/compiler/filter/morph/standard.rb +55 -0
- data/lib/raw/compiler/filter/morph/times.rb +27 -0
- data/lib/raw/compiler/filter/script.rb +116 -0
- data/lib/raw/compiler/filter/squeeze.rb +16 -0
- data/lib/raw/compiler/filter/static_include.rb +74 -0
- data/lib/raw/compiler/filter/template.rb +121 -0
- data/lib/raw/compiler/reloader.rb +96 -0
- data/lib/raw/context.rb +154 -0
- data/lib/raw/context/flash.rb +157 -0
- data/lib/raw/context/global.rb +88 -0
- data/lib/raw/context/request.rb +338 -0
- data/lib/raw/context/response.rb +57 -0
- data/lib/raw/context/session.rb +198 -0
- data/lib/raw/context/session/drb.rb +11 -0
- data/lib/raw/context/session/file.rb +15 -0
- data/lib/raw/context/session/memcached.rb +13 -0
- data/lib/raw/context/session/memory.rb +12 -0
- data/lib/raw/context/session/og.rb +15 -0
- data/lib/raw/context/session/pstore.rb +13 -0
- data/lib/raw/control.rb +18 -0
- data/lib/raw/control/attribute.rb +91 -0
- data/lib/raw/control/attribute/checkbox.rb +25 -0
- data/lib/raw/control/attribute/datetime.rb +21 -0
- data/lib/raw/control/attribute/file.rb +20 -0
- data/lib/raw/control/attribute/fixnum.rb +26 -0
- data/lib/raw/control/attribute/float.rb +26 -0
- data/lib/raw/control/attribute/options.rb +38 -0
- data/lib/raw/control/attribute/password.rb +16 -0
- data/lib/raw/control/attribute/text.rb +16 -0
- data/lib/raw/control/attribute/textarea.rb +16 -0
- data/lib/raw/control/none.rb +16 -0
- data/lib/raw/control/relation.rb +59 -0
- data/lib/raw/control/relation/belongs_to.rb +0 -0
- data/lib/raw/control/relation/has_many.rb +97 -0
- data/lib/raw/control/relation/joins_many.rb +0 -0
- data/lib/raw/control/relation/many_to_many.rb +0 -0
- data/lib/raw/control/relation/refers_to.rb +29 -0
- data/lib/raw/controller.rb +37 -0
- data/lib/raw/controller/publishable.rb +160 -0
- data/lib/raw/dispatcher.rb +209 -0
- data/lib/raw/dispatcher/format.rb +108 -0
- data/lib/raw/dispatcher/format/atom.rb +31 -0
- data/lib/raw/dispatcher/format/css.rb +0 -0
- data/lib/raw/dispatcher/format/html.rb +42 -0
- data/lib/raw/dispatcher/format/json.rb +31 -0
- data/lib/raw/dispatcher/format/rss.rb +33 -0
- data/lib/raw/dispatcher/format/xoxo.rb +31 -0
- data/lib/raw/dispatcher/mounter.rb +60 -0
- data/lib/raw/dispatcher/router.rb +111 -0
- data/lib/raw/errors.rb +19 -0
- data/lib/raw/helper.rb +86 -0
- data/lib/raw/helper/benchmark.rb +23 -0
- data/lib/raw/helper/buffer.rb +60 -0
- data/lib/raw/helper/cookie.rb +32 -0
- data/lib/raw/helper/debug.rb +28 -0
- data/lib/raw/helper/default.rb +16 -0
- data/lib/raw/helper/feed.rb +451 -0
- data/lib/raw/helper/form.rb +284 -0
- data/lib/raw/helper/javascript.rb +59 -0
- data/lib/raw/helper/layout.rb +40 -0
- data/lib/raw/helper/navigation.rb +87 -0
- data/lib/raw/helper/pager.rb +305 -0
- data/lib/raw/helper/table.rb +247 -0
- data/lib/raw/helper/xhtml.rb +218 -0
- data/lib/raw/helper/xml.rb +125 -0
- data/lib/raw/mixin/magick.rb +35 -0
- data/lib/raw/mixin/sweeper.rb +71 -0
- data/lib/raw/mixin/thumbnails.rb +1 -0
- data/lib/raw/mixin/webfile.rb +165 -0
- data/lib/raw/render.rb +271 -0
- data/lib/raw/render/builder.rb +26 -0
- data/lib/raw/render/caching.rb +81 -0
- data/lib/raw/render/call.rb +43 -0
- data/lib/raw/render/send_file.rb +46 -0
- data/lib/raw/render/stream.rb +39 -0
- data/lib/raw/scaffold.rb +13 -0
- data/lib/raw/scaffold/controller.rb +25 -0
- data/lib/raw/scaffold/model.rb +157 -0
- data/lib/raw/test.rb +5 -0
- data/lib/raw/test/assertions.rb +169 -0
- data/lib/raw/test/context.rb +55 -0
- data/lib/raw/test/testcase.rb +79 -0
- data/lib/raw/util/attr.rb +128 -0
- data/lib/raw/util/encode_uri.rb +149 -0
- data/lib/raw/util/html_filter.rb +538 -0
- data/lib/raw/util/markup.rb +130 -0
- data/test/glue/tc_webfile.rb +1 -0
- data/test/nitro/CONFIG.rb +3 -0
- data/test/nitro/adapter/raw_post1.bin +9 -0
- data/test/nitro/adapter/tc_webrick.rb +16 -0
- data/test/nitro/cgi/tc_cookie.rb +14 -0
- data/test/nitro/cgi/tc_request.rb +61 -0
- data/test/nitro/compiler/tc_client_morpher.rb +47 -0
- data/test/nitro/compiler/tc_compiler.rb +25 -0
- data/test/nitro/dispatcher/tc_mounter.rb +47 -0
- data/test/nitro/helper/tc_feed.rb +135 -0
- data/test/nitro/helper/tc_navbar.rb +74 -0
- data/test/nitro/helper/tc_pager.rb +35 -0
- data/test/nitro/helper/tc_table.rb +68 -0
- data/test/nitro/helper/tc_xhtml.rb +19 -0
- data/test/nitro/tc_caching.rb +19 -0
- data/test/nitro/tc_cgi.rb +222 -0
- data/test/nitro/tc_context.rb +17 -0
- data/test/nitro/tc_controller.rb +103 -0
- data/test/nitro/tc_controller_aspect.rb +32 -0
- data/test/nitro/tc_controller_params.rb +885 -0
- data/test/nitro/tc_dispatcher.rb +109 -0
- data/test/nitro/tc_element.rb +85 -0
- data/test/nitro/tc_flash.rb +59 -0
- data/test/nitro/tc_helper.rb +47 -0
- data/test/nitro/tc_render.rb +119 -0
- data/test/nitro/tc_router.rb +61 -0
- data/test/nitro/tc_server.rb +35 -0
- data/test/nitro/tc_session.rb +66 -0
- data/test/nitro/tc_template.rb +71 -0
- data/test/nitro/util/tc_encode_url.rb +87 -0
- data/test/nitro/util/tc_markup.rb +31 -0
- data/test/public/blog/another/very_litle/index.xhtml +1 -0
- data/test/public/blog/inc1.xhtml +2 -0
- data/test/public/blog/inc2.xhtml +1 -0
- data/test/public/blog/list.xhtml +9 -0
- data/test/public/dummy_mailer/registration.xhtml +5 -0
- metadata +244 -0
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
require "facets/more/ann"
|
|
2
|
+
|
|
3
|
+
require "raw/render"
|
|
4
|
+
require "raw/render/caching"
|
|
5
|
+
require "raw/context/flash"
|
|
6
|
+
require "raw/helper"
|
|
7
|
+
require "raw/helper/cookie"
|
|
8
|
+
require "raw/compiler"
|
|
9
|
+
require "raw/compiler/filter/template"
|
|
10
|
+
require "raw/util/encode_uri"
|
|
11
|
+
require "raw/util/markup"
|
|
12
|
+
|
|
13
|
+
module Raw
|
|
14
|
+
|
|
15
|
+
# Include this Mixin to a class to make objects of this class
|
|
16
|
+
# publishable, ie accessible through a standard web (REST)
|
|
17
|
+
# interface.
|
|
18
|
+
|
|
19
|
+
module Publishable
|
|
20
|
+
def self.included(base)
|
|
21
|
+
super
|
|
22
|
+
base.send(:include, Render)
|
|
23
|
+
base.send(:include, Flashing)
|
|
24
|
+
base.send(:include, Caching)
|
|
25
|
+
base.send(:include, Helpers)
|
|
26
|
+
base.helper(EncodeURI)
|
|
27
|
+
base.helper(CookieHelper)
|
|
28
|
+
base.helper(Markup)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Use the method_missing hook to compile the actions
|
|
32
|
+
# for this controller.
|
|
33
|
+
|
|
34
|
+
def method_missing(action, *args)
|
|
35
|
+
if Context.current.application.compiler.compile(self.class, action)
|
|
36
|
+
send(action, *args)
|
|
37
|
+
else
|
|
38
|
+
super
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
class_extension do
|
|
43
|
+
|
|
44
|
+
# The path where this controller is mounted.
|
|
45
|
+
|
|
46
|
+
attr_accessor :mount_path
|
|
47
|
+
|
|
48
|
+
# Return the 'action' methods for this Object. Some
|
|
49
|
+
# dangerous methods from ancestors are removed. All private
|
|
50
|
+
# methods are ignored.
|
|
51
|
+
#--
|
|
52
|
+
# gmosx, TODO: We should optimize this method.
|
|
53
|
+
#++
|
|
54
|
+
|
|
55
|
+
def action_methods
|
|
56
|
+
public_instance_methods - Controller.public_instance_methods
|
|
57
|
+
end
|
|
58
|
+
alias_method :actions, :action_methods
|
|
59
|
+
|
|
60
|
+
# Check if the controller responds to this action.
|
|
61
|
+
|
|
62
|
+
def action?(action)
|
|
63
|
+
action_methods.include?(action.to_s)
|
|
64
|
+
end
|
|
65
|
+
alias_method :respond_to_action?, :action?
|
|
66
|
+
|
|
67
|
+
# Check if the a template for this action and format exists.
|
|
68
|
+
# Returns a valid path or nil.
|
|
69
|
+
|
|
70
|
+
def template?(action, format)
|
|
71
|
+
# Allow for template override using the :template annotation
|
|
72
|
+
#
|
|
73
|
+
# class MyController
|
|
74
|
+
# def myaction
|
|
75
|
+
# end
|
|
76
|
+
# ann :myaction, :template => :another_template
|
|
77
|
+
# end
|
|
78
|
+
|
|
79
|
+
template = ann(action, :template) || action
|
|
80
|
+
|
|
81
|
+
template = template.to_s.gsub(/__/, "/")
|
|
82
|
+
|
|
83
|
+
for dir in ann(:self, :template_dir_stack)
|
|
84
|
+
name = "#{dir}/#{template}".squeeze("/")
|
|
85
|
+
|
|
86
|
+
# attempt to find a template of the form:
|
|
87
|
+
# dir/action.xhtml
|
|
88
|
+
|
|
89
|
+
path = "#{name}.#{format.template_extension}"
|
|
90
|
+
return path if File.exist?(path)
|
|
91
|
+
|
|
92
|
+
# attempt to find a template of the form:
|
|
93
|
+
# dir/action/index.xhtml
|
|
94
|
+
|
|
95
|
+
path = "#{name}/index.#{format.template_extension}"
|
|
96
|
+
return path if File.exist?(path)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
return nil
|
|
100
|
+
end
|
|
101
|
+
alias_method :has_template?, :template?
|
|
102
|
+
alias_method :template_path, :template?
|
|
103
|
+
|
|
104
|
+
# Check if this action or template exists.
|
|
105
|
+
|
|
106
|
+
def action_or_template?(action, format)
|
|
107
|
+
action?(action) or template?(action, format)
|
|
108
|
+
end
|
|
109
|
+
alias_method :respond_to_action_or_template?, :action_or_template?
|
|
110
|
+
|
|
111
|
+
# Aliases an action
|
|
112
|
+
#--
|
|
113
|
+
# gmosx, FIXME: better implementation needed.
|
|
114
|
+
# gmosx, FIXME: copy all annotations.
|
|
115
|
+
#++
|
|
116
|
+
|
|
117
|
+
def alias_action(new, old)
|
|
118
|
+
alias_method new, old
|
|
119
|
+
ann new, :template => old
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Override this method to customize the template_dir_stack.
|
|
123
|
+
# Typically used in controllers defined in reusable Parts.
|
|
124
|
+
# Call super to include the parent class's customizations.
|
|
125
|
+
# Implements some form of template root inheritance,
|
|
126
|
+
# thus allowing for more reusable controllers. Ie you can
|
|
127
|
+
# 'extend' a controller, and only override the templates
|
|
128
|
+
# you want to change. The compiler will traverse the
|
|
129
|
+
# template dir stack and use the templates from parent
|
|
130
|
+
# controllers if they are not overriden.
|
|
131
|
+
#
|
|
132
|
+
# def self.setup_template_dir_stack(stack)
|
|
133
|
+
# super
|
|
134
|
+
# stack << "custom/route/#{self.mount_path}"
|
|
135
|
+
# stack << "another/route"
|
|
136
|
+
# end
|
|
137
|
+
|
|
138
|
+
def setup_template_dir_stack(path)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# This callback is called when this controller is mounted.
|
|
142
|
+
|
|
143
|
+
def mount_at(path)
|
|
144
|
+
@mount_path = path
|
|
145
|
+
|
|
146
|
+
# Setup the template_dir_stack.
|
|
147
|
+
|
|
148
|
+
stack = []
|
|
149
|
+
stack << File.join(Template.root_dir, path).gsub(/\/$/, "")
|
|
150
|
+
self.setup_template_dir_stack(stack)
|
|
151
|
+
stack << File.join(Nitro.proto_path, "template", path).gsub(/\/$/, "")
|
|
152
|
+
ann(:self, :template_dir_stack => stack)
|
|
153
|
+
end
|
|
154
|
+
alias_method :mount, :mount_at
|
|
155
|
+
|
|
156
|
+
end # class_extension
|
|
157
|
+
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
end
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
require "facets/core/module/ancestor"
|
|
2
|
+
|
|
3
|
+
require "raw/dispatcher/router"
|
|
4
|
+
require "raw/dispatcher/mounter"
|
|
5
|
+
require "raw/dispatcher/format"
|
|
6
|
+
|
|
7
|
+
module Raw
|
|
8
|
+
|
|
9
|
+
# The Dispatcher manages a set of controllers. It selects the
|
|
10
|
+
# appropriate Controller and action to handle the given
|
|
11
|
+
# request.
|
|
12
|
+
#
|
|
13
|
+
# This dispatcher intelligently handles RESTful uris according
|
|
14
|
+
# to the following scheme:
|
|
15
|
+
#
|
|
16
|
+
# GET /links GET /links/index Link::Controller#index
|
|
17
|
+
# POST /links POST /links/create Link::Controller#create
|
|
18
|
+
# GET /links;new GET /links/new Link::Controller#new
|
|
19
|
+
# GET /links/1 Link::Controller#view(1)
|
|
20
|
+
# GET /links/1;edit GET /links/edit/1 Link::Controller#edit(1)
|
|
21
|
+
# PUT /links/1 POST /links/update/1 Link::Controller#update
|
|
22
|
+
# DELETE /links/1 GET /links/delete/1 Link::Controller#delete(1)
|
|
23
|
+
# GET /links/index.xml Link::Controller#index # Atom
|
|
24
|
+
# GET /links/index.json Link::Controller#index # JSON
|
|
25
|
+
#
|
|
26
|
+
# The default actions for the various methods are:
|
|
27
|
+
#
|
|
28
|
+
# GET: index
|
|
29
|
+
# POST: create
|
|
30
|
+
# PUT: update
|
|
31
|
+
# DELETE: delete
|
|
32
|
+
|
|
33
|
+
class Dispatcher
|
|
34
|
+
|
|
35
|
+
# The (optional) router.
|
|
36
|
+
|
|
37
|
+
attr_accessor :router
|
|
38
|
+
|
|
39
|
+
# The hash that maps mount paths to controllers.
|
|
40
|
+
|
|
41
|
+
attr_accessor :controllers
|
|
42
|
+
|
|
43
|
+
# The representation formats this dispatcher understands.
|
|
44
|
+
|
|
45
|
+
attr_accessor :formats
|
|
46
|
+
|
|
47
|
+
# Initialize the dispatcher.
|
|
48
|
+
|
|
49
|
+
def initialize(controller_or_map = nil)
|
|
50
|
+
@controllers = {}
|
|
51
|
+
@formats = Nitro::STANDARD_FORMATS.dup
|
|
52
|
+
|
|
53
|
+
if controller_or_map.is_a?(Class)
|
|
54
|
+
mount("/" => controller_or_map)
|
|
55
|
+
elsif controller_or_map.is_a?(Hash)
|
|
56
|
+
mount(controller_or_map)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Mounts a map of controllers.
|
|
61
|
+
|
|
62
|
+
def mount(map)
|
|
63
|
+
for path, controller in map
|
|
64
|
+
self[path] = controller
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Return the controller for the given mount path.
|
|
69
|
+
|
|
70
|
+
def [](path = "/")
|
|
71
|
+
@controllers[path]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Mount a controller to the given mount path.
|
|
75
|
+
|
|
76
|
+
def []=(path, controller)
|
|
77
|
+
controller = resolve_controller(controller)
|
|
78
|
+
|
|
79
|
+
# Customize the class for mounting at the given path.
|
|
80
|
+
controller.mount_at(path) if controller.respond_to? :mount_at
|
|
81
|
+
|
|
82
|
+
# Call the mounted callback to allow for post mount
|
|
83
|
+
# initialization.
|
|
84
|
+
controller.mounted(path) if controller.respond_to? :mounted
|
|
85
|
+
|
|
86
|
+
@controllers[path] = controller
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Dispatch a request. Calls the lower level dispatch method.
|
|
90
|
+
|
|
91
|
+
def dispatch_request(request)
|
|
92
|
+
dispatch(request.uri, request.method)
|
|
93
|
+
end
|
|
94
|
+
alias_method :dispatch_context, :dispatch_request
|
|
95
|
+
|
|
96
|
+
# Dispatch a path given the request method. This method
|
|
97
|
+
# handles fully resolved paths (containing an extension that
|
|
98
|
+
# denotes the expected content type).
|
|
99
|
+
#
|
|
100
|
+
# This method automatically handles 'nice' (seo friendly, elegant)
|
|
101
|
+
# parameters, ie:
|
|
102
|
+
#
|
|
103
|
+
# /links/view/1
|
|
104
|
+
#
|
|
105
|
+
# instead of
|
|
106
|
+
#
|
|
107
|
+
# /links/view?oid=1
|
|
108
|
+
#
|
|
109
|
+
# === Output
|
|
110
|
+
#
|
|
111
|
+
# controller, action, query_string, nice_params, extension
|
|
112
|
+
#
|
|
113
|
+
#--
|
|
114
|
+
# Lower level, useful for testing.
|
|
115
|
+
#++
|
|
116
|
+
|
|
117
|
+
def dispatch(uri, method = :get)
|
|
118
|
+
# Extract the query string.
|
|
119
|
+
|
|
120
|
+
path, query = uri.split("?", 2)
|
|
121
|
+
|
|
122
|
+
# Try to route the path.
|
|
123
|
+
|
|
124
|
+
path = @router.route(path) if @router
|
|
125
|
+
|
|
126
|
+
# The characters after the last '.' in the path form the
|
|
127
|
+
# extension that itself represents the expected response
|
|
128
|
+
# content type.
|
|
129
|
+
|
|
130
|
+
ext = File.extname(path)[1..-1] || "html"
|
|
131
|
+
|
|
132
|
+
# The resource representation format for this request.
|
|
133
|
+
|
|
134
|
+
unless format = Context.current.format = @formats.by_extension[ext]
|
|
135
|
+
raise ActionError.new("Cannot respond to '#{path}' using the '#{ext}' format representation.")
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Remove the extension from the path.
|
|
139
|
+
|
|
140
|
+
path = path.gsub(/\.(.*)$/, '')
|
|
141
|
+
|
|
142
|
+
# Try to extract the controller from the path (that may also
|
|
143
|
+
# include 'nice' parameters). This algorithm tries to find
|
|
144
|
+
# the bigest substring of the path that represents a mount
|
|
145
|
+
# path for a controller.
|
|
146
|
+
|
|
147
|
+
key = path.dup
|
|
148
|
+
|
|
149
|
+
while (controller = @controllers[key]).nil?
|
|
150
|
+
key = key[%r{^(/.+)/.+$}, 1] || '/'
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
# Try to extract the controller from the path. This
|
|
154
|
+
# algorithm tries to find the bigest substring of the path
|
|
155
|
+
# that represents an action of this controller.
|
|
156
|
+
#
|
|
157
|
+
# The algorithm respects action name conventions, ie
|
|
158
|
+
# simple/sub/action maps to simple__sub__action.
|
|
159
|
+
|
|
160
|
+
action = key = path.sub(%r{^#{key}}, '').gsub(%r{^/}, '').gsub(%r{/}, '__')
|
|
161
|
+
|
|
162
|
+
while (!action.blank?) and !controller.action_or_template?(action, format)
|
|
163
|
+
action = action[%r{^(.+)__.+$}, 1]
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Extract the 'nice' parameters.
|
|
167
|
+
|
|
168
|
+
params = key.sub(%r{^#{action}}, '').gsub(/^__/, '').split('__')
|
|
169
|
+
|
|
170
|
+
# Do we have an action?
|
|
171
|
+
|
|
172
|
+
if action.blank?
|
|
173
|
+
# Try to use a standard action for this http method.
|
|
174
|
+
|
|
175
|
+
case method
|
|
176
|
+
when :get
|
|
177
|
+
action = "index"
|
|
178
|
+
|
|
179
|
+
when :post
|
|
180
|
+
action = "create"
|
|
181
|
+
|
|
182
|
+
when :delete
|
|
183
|
+
action = "delete"
|
|
184
|
+
|
|
185
|
+
when :put
|
|
186
|
+
action = "update"
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
unless controller.action_or_template?(action, format)
|
|
190
|
+
raise ActionError.new("Cannot respond to '#{path}' using '#{controller}'")
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
return controller, "#{action}___super", query, params, ext
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
private
|
|
198
|
+
|
|
199
|
+
def resolve_controller(controller)
|
|
200
|
+
unless controller.ancestor?(Controller) or controller.ancestor?(Publishable)
|
|
201
|
+
controller.send(:include, Publishable)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
return controller
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
end
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
module Raw
|
|
2
|
+
|
|
3
|
+
# A REST Resource Representation format.
|
|
4
|
+
|
|
5
|
+
class Format
|
|
6
|
+
|
|
7
|
+
# The name of this format.
|
|
8
|
+
|
|
9
|
+
attr_accessor :name
|
|
10
|
+
|
|
11
|
+
# The resource content type. Typically the resource MIME type
|
|
12
|
+
# is used.
|
|
13
|
+
|
|
14
|
+
attr_accessor :content_type
|
|
15
|
+
alias_method :mime_type, :content_type
|
|
16
|
+
|
|
17
|
+
# The default resource extension.
|
|
18
|
+
|
|
19
|
+
attr_accessor :extension
|
|
20
|
+
|
|
21
|
+
# The default template extension.
|
|
22
|
+
|
|
23
|
+
attr_accessor :template_extension
|
|
24
|
+
|
|
25
|
+
def to_s
|
|
26
|
+
@name
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Apply filters to the template source. The original template
|
|
30
|
+
# representation must be transformed to executable Ruby code
|
|
31
|
+
# at the end.
|
|
32
|
+
|
|
33
|
+
def filter_template(source)
|
|
34
|
+
return source
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# This callback is called before the action is executed with
|
|
38
|
+
# this format.
|
|
39
|
+
|
|
40
|
+
def before_action(controller, context)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# This callback is called after the action is executed with
|
|
44
|
+
# this format.
|
|
45
|
+
|
|
46
|
+
def after_action(controller, context)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# A Format Manager. Provides useful methods for fast Format
|
|
52
|
+
# lookup.
|
|
53
|
+
|
|
54
|
+
class FormatManager
|
|
55
|
+
# Formats indexed by name.
|
|
56
|
+
|
|
57
|
+
attr_accessor :by_name
|
|
58
|
+
|
|
59
|
+
# Formats indexed by mime type.
|
|
60
|
+
|
|
61
|
+
attr_accessor :by_mime_type
|
|
62
|
+
|
|
63
|
+
# Formats indexed by extension.
|
|
64
|
+
|
|
65
|
+
attr_accessor :by_extension
|
|
66
|
+
|
|
67
|
+
def initialize(*formats)
|
|
68
|
+
@by_name = {}
|
|
69
|
+
@by_mime_type = {}
|
|
70
|
+
@by_extension = {}
|
|
71
|
+
|
|
72
|
+
for format in formats.flatten
|
|
73
|
+
put(format)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Add a new format to the manager.
|
|
78
|
+
|
|
79
|
+
def put(format)
|
|
80
|
+
if format.is_a? Class
|
|
81
|
+
format = format.new
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
@by_name[format.name] = format
|
|
85
|
+
@by_mime_type[format.mime_type] = format
|
|
86
|
+
@by_extension[format.extension] = format
|
|
87
|
+
end
|
|
88
|
+
alias_method :<<, :put
|
|
89
|
+
|
|
90
|
+
# Lookup a format by name.
|
|
91
|
+
|
|
92
|
+
def [](name)
|
|
93
|
+
@by_name[name]
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
require "raw/dispatcher/format/html"
|
|
99
|
+
require "raw/dispatcher/format/atom"
|
|
100
|
+
require "raw/dispatcher/format/rss"
|
|
101
|
+
require "raw/dispatcher/format/json"
|
|
102
|
+
require "raw/dispatcher/format/xoxo"
|
|
103
|
+
|
|
104
|
+
STANDARD_FORMATS = FormatManager.new(
|
|
105
|
+
HTMLFormat, ATOMFormat, RSSFormat, JSONFormat, XOXOFormat
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
end
|