wycats-merb-core 0.9.8
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/CHANGELOG +992 -0
- data/CONTRIBUTORS +94 -0
- data/LICENSE +20 -0
- data/PUBLIC_CHANGELOG +142 -0
- data/README +21 -0
- data/Rakefile +458 -0
- data/TODO +0 -0
- data/bin/merb +11 -0
- data/bin/merb-specs +5 -0
- data/lib/merb-core.rb +598 -0
- data/lib/merb-core/autoload.rb +31 -0
- data/lib/merb-core/bootloader.rb +717 -0
- data/lib/merb-core/config.rb +305 -0
- data/lib/merb-core/constants.rb +45 -0
- data/lib/merb-core/controller/abstract_controller.rb +568 -0
- data/lib/merb-core/controller/exceptions.rb +315 -0
- data/lib/merb-core/controller/merb_controller.rb +256 -0
- data/lib/merb-core/controller/mime.rb +107 -0
- data/lib/merb-core/controller/mixins/authentication.rb +123 -0
- data/lib/merb-core/controller/mixins/conditional_get.rb +83 -0
- data/lib/merb-core/controller/mixins/controller.rb +319 -0
- data/lib/merb-core/controller/mixins/render.rb +513 -0
- data/lib/merb-core/controller/mixins/responder.rb +469 -0
- data/lib/merb-core/controller/template.rb +254 -0
- data/lib/merb-core/core_ext.rb +9 -0
- data/lib/merb-core/core_ext/hash.rb +7 -0
- data/lib/merb-core/core_ext/kernel.rb +340 -0
- data/lib/merb-core/dispatch/cookies.rb +130 -0
- data/lib/merb-core/dispatch/default_exception/default_exception.rb +93 -0
- data/lib/merb-core/dispatch/default_exception/views/_css.html.erb +198 -0
- data/lib/merb-core/dispatch/default_exception/views/_javascript.html.erb +73 -0
- data/lib/merb-core/dispatch/default_exception/views/index.html.erb +94 -0
- data/lib/merb-core/dispatch/dispatcher.rb +176 -0
- data/lib/merb-core/dispatch/request.rb +729 -0
- data/lib/merb-core/dispatch/router.rb +151 -0
- data/lib/merb-core/dispatch/router/behavior.rb +566 -0
- data/lib/merb-core/dispatch/router/cached_proc.rb +52 -0
- data/lib/merb-core/dispatch/router/resources.rb +191 -0
- data/lib/merb-core/dispatch/router/route.rb +511 -0
- data/lib/merb-core/dispatch/session.rb +222 -0
- data/lib/merb-core/dispatch/session/container.rb +74 -0
- data/lib/merb-core/dispatch/session/cookie.rb +173 -0
- data/lib/merb-core/dispatch/session/memcached.rb +68 -0
- data/lib/merb-core/dispatch/session/memory.rb +99 -0
- data/lib/merb-core/dispatch/session/store_container.rb +150 -0
- data/lib/merb-core/dispatch/worker.rb +28 -0
- data/lib/merb-core/gem_ext/erubis.rb +77 -0
- data/lib/merb-core/logger.rb +203 -0
- data/lib/merb-core/plugins.rb +67 -0
- data/lib/merb-core/rack.rb +25 -0
- data/lib/merb-core/rack/adapter.rb +44 -0
- data/lib/merb-core/rack/adapter/ebb.rb +25 -0
- data/lib/merb-core/rack/adapter/evented_mongrel.rb +26 -0
- data/lib/merb-core/rack/adapter/fcgi.rb +17 -0
- data/lib/merb-core/rack/adapter/irb.rb +118 -0
- data/lib/merb-core/rack/adapter/mongrel.rb +26 -0
- data/lib/merb-core/rack/adapter/runner.rb +28 -0
- data/lib/merb-core/rack/adapter/swiftiplied_mongrel.rb +26 -0
- data/lib/merb-core/rack/adapter/thin.rb +39 -0
- data/lib/merb-core/rack/adapter/thin_turbo.rb +24 -0
- data/lib/merb-core/rack/adapter/webrick.rb +36 -0
- data/lib/merb-core/rack/application.rb +32 -0
- data/lib/merb-core/rack/handler/mongrel.rb +97 -0
- data/lib/merb-core/rack/middleware.rb +20 -0
- data/lib/merb-core/rack/middleware/conditional_get.rb +29 -0
- data/lib/merb-core/rack/middleware/content_length.rb +18 -0
- data/lib/merb-core/rack/middleware/csrf.rb +73 -0
- data/lib/merb-core/rack/middleware/path_prefix.rb +31 -0
- data/lib/merb-core/rack/middleware/profiler.rb +19 -0
- data/lib/merb-core/rack/middleware/static.rb +45 -0
- data/lib/merb-core/rack/middleware/tracer.rb +20 -0
- data/lib/merb-core/server.rb +284 -0
- data/lib/merb-core/tasks/audit.rake +68 -0
- data/lib/merb-core/tasks/gem_management.rb +229 -0
- data/lib/merb-core/tasks/merb.rb +1 -0
- data/lib/merb-core/tasks/merb_rake_helper.rb +80 -0
- data/lib/merb-core/tasks/stats.rake +71 -0
- data/lib/merb-core/test.rb +11 -0
- data/lib/merb-core/test/helpers.rb +9 -0
- data/lib/merb-core/test/helpers/controller_helper.rb +8 -0
- data/lib/merb-core/test/helpers/multipart_request_helper.rb +175 -0
- data/lib/merb-core/test/helpers/request_helper.rb +393 -0
- data/lib/merb-core/test/helpers/route_helper.rb +39 -0
- data/lib/merb-core/test/helpers/view_helper.rb +121 -0
- data/lib/merb-core/test/matchers.rb +9 -0
- data/lib/merb-core/test/matchers/controller_matchers.rb +351 -0
- data/lib/merb-core/test/matchers/route_matchers.rb +137 -0
- data/lib/merb-core/test/matchers/view_matchers.rb +375 -0
- data/lib/merb-core/test/run_specs.rb +49 -0
- data/lib/merb-core/test/tasks/spectasks.rb +68 -0
- data/lib/merb-core/test/test_ext/hpricot.rb +32 -0
- data/lib/merb-core/test/test_ext/object.rb +14 -0
- data/lib/merb-core/test/test_ext/string.rb +14 -0
- data/lib/merb-core/vendor/facets.rb +2 -0
- data/lib/merb-core/vendor/facets/dictionary.rb +433 -0
- data/lib/merb-core/vendor/facets/inflect.rb +342 -0
- data/lib/merb-core/version.rb +3 -0
- metadata +253 -0
@@ -0,0 +1,469 @@
|
|
1
|
+
require 'enumerator'
|
2
|
+
require 'merb-core/controller/mime'
|
3
|
+
require "merb-core/vendor/facets/dictionary"
|
4
|
+
|
5
|
+
module Merb
|
6
|
+
# The ResponderMixin adds methods that help you manage what
|
7
|
+
# formats your controllers have available, determine what format(s)
|
8
|
+
# the client requested and is capable of handling, and perform
|
9
|
+
# content negotiation to pick the proper content format to
|
10
|
+
# deliver.
|
11
|
+
#
|
12
|
+
# If you hear someone say "Use provides" they're talking about the
|
13
|
+
# Responder. If you hear someone ask "What happened to respond_to?"
|
14
|
+
# it was replaced by provides and the other Responder methods.
|
15
|
+
#
|
16
|
+
# == A simple example
|
17
|
+
#
|
18
|
+
# The best way to understand how all of these pieces fit together is
|
19
|
+
# with an example. Here's a simple web-service ready resource that
|
20
|
+
# provides a list of all the widgets we know about. The widget list is
|
21
|
+
# available in 3 formats: :html (the default), plus :xml and :text.
|
22
|
+
#
|
23
|
+
# class Widgets < Application
|
24
|
+
# provides :html # This is the default, but you can
|
25
|
+
# # be explicit if you like.
|
26
|
+
# provides :xml, :text
|
27
|
+
#
|
28
|
+
# def index
|
29
|
+
# @widgets = Widget.fetch
|
30
|
+
# render @widgets
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
# Let's look at some example requests for this list of widgets. We'll
|
35
|
+
# assume they're all GET requests, but that's only to make the examples
|
36
|
+
# easier; this works for the full set of RESTful methods.
|
37
|
+
#
|
38
|
+
# 1. The simplest case, /widgets.html
|
39
|
+
# Since the request includes a specific format (.html) we know
|
40
|
+
# what format to return. Since :html is in our list of provided
|
41
|
+
# formats, that's what we'll return. +render+ will look
|
42
|
+
# for an index.html.erb (or another template format
|
43
|
+
# like index.html.mab; see the documentation on Template engines)
|
44
|
+
#
|
45
|
+
# 2. Almost as simple, /widgets.xml
|
46
|
+
# This is very similar. They want :xml, we have :xml, so
|
47
|
+
# that's what they get. If +render+ doesn't find an
|
48
|
+
# index.xml.builder or similar template, it will call +to_xml+
|
49
|
+
# on @widgets. This may or may not do something useful, but you can
|
50
|
+
# see how it works.
|
51
|
+
#
|
52
|
+
# 3. A browser request for /widgets
|
53
|
+
# This time the URL doesn't say what format is being requested, so
|
54
|
+
# we'll look to the HTTP Accept: header. If it's '*/*' (anything),
|
55
|
+
# we'll use the first format on our list, :html by default.
|
56
|
+
#
|
57
|
+
# If it parses to a list of accepted formats, we'll look through
|
58
|
+
# them, in order, until we find one we have available. If we find
|
59
|
+
# one, we'll use that. Otherwise, we can't fulfill the request:
|
60
|
+
# they asked for a format we don't have. So we raise
|
61
|
+
# 406: Not Acceptable.
|
62
|
+
#
|
63
|
+
# == A more complex example
|
64
|
+
#
|
65
|
+
# Sometimes you don't have the same code to handle each available
|
66
|
+
# format. Sometimes you need to load different data to serve
|
67
|
+
# /widgets.xml versus /widgets.txt. In that case, you can use
|
68
|
+
# +content_type+ to determine what format will be delivered.
|
69
|
+
#
|
70
|
+
# class Widgets < Application
|
71
|
+
# def action1
|
72
|
+
# if content_type == :text
|
73
|
+
# Widget.load_text_formatted(params[:id])
|
74
|
+
# else
|
75
|
+
# render
|
76
|
+
# end
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# def action2
|
80
|
+
# case content_type
|
81
|
+
# when :html
|
82
|
+
# handle_html()
|
83
|
+
# when :xml
|
84
|
+
# handle_xml()
|
85
|
+
# when :text
|
86
|
+
# handle_text()
|
87
|
+
# else
|
88
|
+
# render
|
89
|
+
# end
|
90
|
+
# end
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# You can do any standard Ruby flow control using +content_type+. If
|
94
|
+
# you don't call it yourself, it will be called (triggering content
|
95
|
+
# negotiation) by +render+.
|
96
|
+
#
|
97
|
+
# Once +content_type+ has been called, the output format is frozen,
|
98
|
+
# and none of the provides methods can be used.
|
99
|
+
module ResponderMixin
|
100
|
+
|
101
|
+
TYPES = Dictionary.new
|
102
|
+
MIMES = {}
|
103
|
+
|
104
|
+
class ContentTypeAlreadySet < StandardError; end
|
105
|
+
|
106
|
+
# ==== Parameters
|
107
|
+
# base<Module>:: The module that ResponderMixin was mixed into
|
108
|
+
def self.included(base)
|
109
|
+
base.extend(ClassMethods)
|
110
|
+
base.class_eval do
|
111
|
+
class_inheritable_accessor :class_provided_formats
|
112
|
+
self.class_provided_formats = []
|
113
|
+
end
|
114
|
+
base.reset_provides
|
115
|
+
end
|
116
|
+
|
117
|
+
module ClassMethods
|
118
|
+
|
119
|
+
# Adds symbols representing formats to the controller's default list of
|
120
|
+
# provided_formats. These will apply to every action in the controller,
|
121
|
+
# unless modified in the action. If the last argument is a Hash or an
|
122
|
+
# Array, these are regarded as arguments to pass to the to_<mime_type>
|
123
|
+
# method as needed.
|
124
|
+
#
|
125
|
+
# ==== Parameters
|
126
|
+
# *formats<Symbol>::
|
127
|
+
# A list of mime-types that the controller should provide.
|
128
|
+
#
|
129
|
+
# ==== Returns
|
130
|
+
# Array[Symbol]:: List of formats passed in.
|
131
|
+
#
|
132
|
+
# ==== Examples
|
133
|
+
# provides :html, :xml
|
134
|
+
#---
|
135
|
+
# @public
|
136
|
+
def provides(*formats)
|
137
|
+
self.class_provided_formats |= formats
|
138
|
+
end
|
139
|
+
|
140
|
+
# This class should only provide the formats listed here, despite any
|
141
|
+
# other definitions previously or in superclasses.
|
142
|
+
#
|
143
|
+
# ==== Parameters
|
144
|
+
# *formats<Symbol>:: Registered mime-types.
|
145
|
+
#
|
146
|
+
# ==== Returns
|
147
|
+
# Array[Symbol]:: List of formats passed in.
|
148
|
+
#
|
149
|
+
#---
|
150
|
+
# @public
|
151
|
+
def only_provides(*formats)
|
152
|
+
clear_provides
|
153
|
+
provides(*formats)
|
154
|
+
end
|
155
|
+
|
156
|
+
# This class should not provide any of this list of formats, despite any.
|
157
|
+
# other definitions previously or in superclasses.
|
158
|
+
#
|
159
|
+
# ==== Parameters
|
160
|
+
# *formats<Symbol>:: Registered mime-types.
|
161
|
+
#
|
162
|
+
# ==== Returns
|
163
|
+
# Array[Symbol]::
|
164
|
+
# List of formats that remain after removing the ones not to provide.
|
165
|
+
#
|
166
|
+
#---
|
167
|
+
# @public
|
168
|
+
def does_not_provide(*formats)
|
169
|
+
self.class_provided_formats -= formats
|
170
|
+
end
|
171
|
+
|
172
|
+
# Clear the list of provides.
|
173
|
+
#
|
174
|
+
# ==== Returns
|
175
|
+
# Array:: An empty Array.
|
176
|
+
def clear_provides
|
177
|
+
self.class_provided_formats.clear
|
178
|
+
end
|
179
|
+
|
180
|
+
# Reset the list of provides to include only :html.
|
181
|
+
#
|
182
|
+
# ==== Returns
|
183
|
+
# Array[Symbol]:: [:html].
|
184
|
+
def reset_provides
|
185
|
+
only_provides(:html)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
# ==== Returns
|
190
|
+
# Array[Symbol]::
|
191
|
+
# The current list of formats provided for this instance of the
|
192
|
+
# controller. It starts with what has been set in the controller (or
|
193
|
+
# :html by default) but can be modifed on a per-action basis.
|
194
|
+
def _provided_formats
|
195
|
+
@_provided_formats ||= class_provided_formats.dup
|
196
|
+
end
|
197
|
+
|
198
|
+
# Adds formats to the list of provided formats for this particular request.
|
199
|
+
# Usually used to add formats to a single action. See also the
|
200
|
+
# controller-level provides that affects all actions in a controller.
|
201
|
+
#
|
202
|
+
# ==== Parameters
|
203
|
+
# *formats<Symbol>::
|
204
|
+
# A list of formats to add to the per-action list of provided formats.
|
205
|
+
#
|
206
|
+
# ==== Raises
|
207
|
+
# Merb::ResponderMixin::ContentTypeAlreadySet::
|
208
|
+
# Content negotiation already occured, and the content_type is set.
|
209
|
+
#
|
210
|
+
# ==== Returns
|
211
|
+
# Array[Symbol]:: List of formats passed in.
|
212
|
+
#
|
213
|
+
#---
|
214
|
+
# @public
|
215
|
+
def provides(*formats)
|
216
|
+
if @_content_type
|
217
|
+
raise ContentTypeAlreadySet, "Cannot modify provided_formats because content_type has already been set"
|
218
|
+
end
|
219
|
+
@_provided_formats = self._provided_formats | formats # merges with class_provided_formats if not already
|
220
|
+
end
|
221
|
+
|
222
|
+
# Sets list of provided formats for this particular request. Usually used
|
223
|
+
# to limit formats to a single action. See also the controller-level
|
224
|
+
# only_provides that affects all actions in a controller.
|
225
|
+
#
|
226
|
+
# ==== Parameters
|
227
|
+
# *formats<Symbol>::
|
228
|
+
# A list of formats to use as the per-action list of provided formats.
|
229
|
+
#
|
230
|
+
# ==== Returns
|
231
|
+
# Array[Symbol]:: List of formats passed in.
|
232
|
+
#
|
233
|
+
#---
|
234
|
+
# @public
|
235
|
+
def only_provides(*formats)
|
236
|
+
@_provided_formats = []
|
237
|
+
provides(*formats)
|
238
|
+
end
|
239
|
+
|
240
|
+
# Removes formats from the list of provided formats for this particular
|
241
|
+
# request. Usually used to remove formats from a single action. See
|
242
|
+
# also the controller-level does_not_provide that affects all actions in a
|
243
|
+
# controller.
|
244
|
+
#
|
245
|
+
# ==== Parameters
|
246
|
+
# *formats<Symbol>:: Registered mime-type
|
247
|
+
#
|
248
|
+
# ==== Returns
|
249
|
+
# Array[Symbol]::
|
250
|
+
# List of formats that remain after removing the ones not to provide.
|
251
|
+
#
|
252
|
+
#---
|
253
|
+
# @public
|
254
|
+
def does_not_provide(*formats)
|
255
|
+
@_provided_formats -= formats.flatten
|
256
|
+
end
|
257
|
+
|
258
|
+
# Do the content negotiation:
|
259
|
+
# 1. if params[:format] is there, and provided, use it
|
260
|
+
# 2. Parse the Accept header
|
261
|
+
# 3. If it's */*, use the first provided format
|
262
|
+
# 4. Look for one that is provided, in order of request
|
263
|
+
# 5. Raise 406 if none found
|
264
|
+
def _perform_content_negotiation
|
265
|
+
if (fmt = params[:format]) && !fmt.empty?
|
266
|
+
accepts = [fmt.to_sym]
|
267
|
+
elsif request.accept =~ %r{^(text/html|\*/\*)} && _provided_formats.first == :html
|
268
|
+
# Handle the common case of text/html and :html provided after checking :format
|
269
|
+
return :html
|
270
|
+
else
|
271
|
+
accepts = Responder.parse(request.accept).map {|t| t.to_sym}.compact
|
272
|
+
end
|
273
|
+
|
274
|
+
# no need to make a bunch of method calls to _provided_formats
|
275
|
+
provided_formats = _provided_formats
|
276
|
+
|
277
|
+
specifics = accepts & provided_formats
|
278
|
+
return specifics.first unless specifics.length == 0
|
279
|
+
return provided_formats.first if accepts.include?(:all) && !provided_formats.empty?
|
280
|
+
|
281
|
+
message = "A format (%s) that isn't provided (%s) has been requested. "
|
282
|
+
message += "Make sure the action provides the format, and be "
|
283
|
+
message += "careful of before filters which won't recognize "
|
284
|
+
message += "formats provided within actions."
|
285
|
+
raise Merb::ControllerExceptions::NotAcceptable,
|
286
|
+
(message % [accepts.join(', '), provided_formats.join(', ')])
|
287
|
+
end
|
288
|
+
|
289
|
+
# Returns the output format for this request, based on the
|
290
|
+
# provided formats, <tt>params[:format]</tt> and the client's HTTP
|
291
|
+
# Accept header.
|
292
|
+
#
|
293
|
+
# The first time this is called, it triggers content negotiation
|
294
|
+
# and caches the value. Once you call +content_type+ you can
|
295
|
+
# not set or change the list of provided formats.
|
296
|
+
#
|
297
|
+
# Called automatically by +render+, so you should only call it if
|
298
|
+
# you need the value, not to trigger content negotiation.
|
299
|
+
#
|
300
|
+
# ==== Parameters
|
301
|
+
# fmt<String>::
|
302
|
+
# An optional format to use instead of performing content negotiation.
|
303
|
+
# This can be used to pass in the values of opts[:format] from the
|
304
|
+
# render function to short-circuit content-negotiation when it's not
|
305
|
+
# necessary. This optional parameter should not be considered part
|
306
|
+
# of the public API.
|
307
|
+
#
|
308
|
+
# ==== Returns
|
309
|
+
# Symbol:: The content-type that will be used for this controller.
|
310
|
+
#
|
311
|
+
#---
|
312
|
+
# @public
|
313
|
+
def content_type(fmt = nil)
|
314
|
+
self.content_type = (fmt || _perform_content_negotiation) unless @_content_type
|
315
|
+
@_content_type
|
316
|
+
end
|
317
|
+
|
318
|
+
# Sets the content type of the current response to a value based on
|
319
|
+
# a passed in key. The Content-Type header will be set to the first
|
320
|
+
# registered header for the mime-type.
|
321
|
+
#
|
322
|
+
# ==== Parameters
|
323
|
+
# type<Symbol>:: The content type.
|
324
|
+
#
|
325
|
+
# ==== Raises
|
326
|
+
# ArgumentError:: type is not in the list of registered mime-types.
|
327
|
+
#
|
328
|
+
# ==== Returns
|
329
|
+
# Symbol:: The content-type that was passed in.
|
330
|
+
#
|
331
|
+
#---
|
332
|
+
# @semipublic
|
333
|
+
def content_type=(type)
|
334
|
+
unless Merb.available_mime_types.has_key?(type)
|
335
|
+
raise Merb::ControllerExceptions::NotAcceptable.new("Unknown content_type for response: #{type}")
|
336
|
+
end
|
337
|
+
|
338
|
+
@_content_type = type
|
339
|
+
|
340
|
+
mime = Merb.available_mime_types[type]
|
341
|
+
|
342
|
+
headers["Content-Type"] = mime[:content_type]
|
343
|
+
|
344
|
+
# merge any format specific response headers
|
345
|
+
mime[:response_headers].each { |k,v| headers[k] ||= v }
|
346
|
+
|
347
|
+
# if given, use a block to finetune any runtime headers
|
348
|
+
mime[:response_block].call(self) if mime[:response_block]
|
349
|
+
|
350
|
+
@_content_type
|
351
|
+
end
|
352
|
+
|
353
|
+
end
|
354
|
+
|
355
|
+
class Responder
|
356
|
+
# Parses the raw accept header into an array of sorted AcceptType objects.
|
357
|
+
#
|
358
|
+
# ==== Parameters
|
359
|
+
# accept_header<~to_s>:: The raw accept header.
|
360
|
+
#
|
361
|
+
# ==== Returns
|
362
|
+
# Array[AcceptType]:: The accepted types.
|
363
|
+
def self.parse(accept_header)
|
364
|
+
headers = accept_header.split(/,/)
|
365
|
+
idx, list = 0, []
|
366
|
+
while idx < headers.size
|
367
|
+
list << AcceptType.new(headers[idx], idx)
|
368
|
+
idx += 1
|
369
|
+
end
|
370
|
+
list.sort
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
class AcceptType
|
375
|
+
attr_reader :media_range, :quality, :index, :type, :sub_type
|
376
|
+
|
377
|
+
# ==== Parameters
|
378
|
+
# entry<String>:: The accept type pattern
|
379
|
+
# index<Fixnum>::
|
380
|
+
# The index used for sorting accept types. A lower value indicates higher
|
381
|
+
# priority.
|
382
|
+
def initialize(entry,index)
|
383
|
+
@index = index
|
384
|
+
|
385
|
+
entry =~ /\s*([^;\s]*)\s*(;\s*q=\s*(.*))?/
|
386
|
+
@media_range, quality = $1, $3
|
387
|
+
|
388
|
+
@type, @sub_type = @media_range.split(%r{/})
|
389
|
+
(quality ||= 0.0) if @media_range == "*/*"
|
390
|
+
@quality = quality ? (quality.to_f * 100).to_i : 100
|
391
|
+
@quality *= (mime && mime[:default_quality] || 1)
|
392
|
+
end
|
393
|
+
|
394
|
+
# Compares two accept types for sorting purposes.
|
395
|
+
#
|
396
|
+
# ==== Parameters
|
397
|
+
# entry<AcceptType>:: The accept type to compare.
|
398
|
+
#
|
399
|
+
# ==== Returns
|
400
|
+
# Fixnum::
|
401
|
+
# -1, 0 or 1, depending on whether entry has a lower, equal or higher
|
402
|
+
# priority than the accept type being compared.
|
403
|
+
def <=>(entry)
|
404
|
+
if entry.quality == quality
|
405
|
+
@index <=> entry.index
|
406
|
+
else
|
407
|
+
entry.quality <=> @quality
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
|
412
|
+
# ==== Parameters
|
413
|
+
# entry<AcceptType>:: The accept type to compare.
|
414
|
+
#
|
415
|
+
# ==== Returns
|
416
|
+
# Boolean::
|
417
|
+
# True if the accept types are equal, i.e. if the synonyms for this
|
418
|
+
# accept type includes the entry media range.
|
419
|
+
def eql?(entry)
|
420
|
+
synonyms.include?(entry.media_range)
|
421
|
+
end
|
422
|
+
|
423
|
+
# An alias for eql?.
|
424
|
+
def ==(entry); eql?(entry); end
|
425
|
+
|
426
|
+
# ==== Returns
|
427
|
+
# Fixnum:: A hash based on the super range.
|
428
|
+
def hash; super_range.hash; end
|
429
|
+
|
430
|
+
# ==== Returns
|
431
|
+
# Array[String]::
|
432
|
+
# All Accept header values, such as "text/html", that match this type.
|
433
|
+
def synonyms
|
434
|
+
return @syns if @syns
|
435
|
+
if _mime = mime
|
436
|
+
@syns = _mime[:accepts]
|
437
|
+
else
|
438
|
+
@syns = []
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
def mime
|
443
|
+
@mime ||= Merb.available_mime_types[Merb::ResponderMixin::MIMES[@media_range]]
|
444
|
+
end
|
445
|
+
|
446
|
+
# ==== Returns
|
447
|
+
# String::
|
448
|
+
# The primary media range for this accept type, i.e. either the first
|
449
|
+
# synonym or, if none exist, the media range.
|
450
|
+
def super_range
|
451
|
+
synonyms.first || @media_range
|
452
|
+
end
|
453
|
+
|
454
|
+
# ==== Returns
|
455
|
+
# Symbol: The type as a symbol, e.g. :html.
|
456
|
+
def to_sym
|
457
|
+
Merb.available_mime_types.select{|k,v|
|
458
|
+
v[:accepts] == synonyms || v[:accepts][0] == synonyms[0]}.flatten.first
|
459
|
+
end
|
460
|
+
|
461
|
+
# ==== Returns
|
462
|
+
# String:: The accept type as a string, i.e. the media range.
|
463
|
+
def to_s
|
464
|
+
@media_range
|
465
|
+
end
|
466
|
+
|
467
|
+
end
|
468
|
+
|
469
|
+
end
|