merb-core 1.0.4 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -66,7 +66,7 @@ spec = Gem::Specification.new do |s|
66
66
  s.add_dependency "rspec"
67
67
  s.add_dependency "rack"
68
68
  s.add_dependency "mime-types"
69
- s.add_dependency "thor", ">= 0.9.7"
69
+ s.add_dependency "thor", ">= 0.9.9"
70
70
  # this escalates to "regular" dependencies, comment it out
71
71
  # for now. RubyGems need some love.
72
72
  #s.add_development_dependency "libxml-ruby"
@@ -1,31 +1,30 @@
1
+ require 'merb-core/core_ext'
2
+ require "merb-core/controller/exceptions"
3
+ require "merb-core/controller/mixins/responder"
4
+ require "merb-core/controller/mixins/render"
5
+ require "merb-core/controller/mixins/authentication"
6
+ require "merb-core/controller/mixins/conditional_get"
7
+ require "merb-core/controller/mixins/controller"
8
+ require "merb-core/controller/abstract_controller"
9
+ require "merb-core/controller/template"
10
+ require "merb-core/controller/merb_controller"
11
+ require "merb-core/bootloader"
12
+ require "merb-core/config"
13
+ require "merb-core/constants"
14
+ require "merb-core/dispatch/dispatcher"
15
+ require "merb-core/plugins"
16
+ require "merb-core/rack"
17
+ require "merb-core/dispatch/request"
18
+ require "merb-core/dispatch/request_parsers.rb"
19
+ require "merb-core/dispatch/router"
20
+ require "merb-core/dispatch/worker"
21
+
1
22
  module Merb
2
- autoload :AbstractController, "merb-core/controller/abstract_controller"
3
- autoload :BootLoader, "merb-core/bootloader"
4
- autoload :Config, "merb-core/config"
5
- autoload :Const, "merb-core/constants"
6
- autoload :ConditionalGetMixin, "merb-core/controller/mixins/conditional_get"
7
- autoload :ControllerMixin, "merb-core/controller/mixins/controller"
8
- autoload :ControllerExceptions, "merb-core/controller/exceptions"
9
- autoload :Dispatcher, "merb-core/dispatch/dispatcher"
10
- autoload :AuthenticationMixin, "merb-core/controller/mixins/authentication"
11
- autoload :BasicAuthenticationMixin, "merb-core/controller/mixins/authentication/basic"
12
- autoload :ErubisCaptureMixin, "merb-core/controller/mixins/erubis_capture"
13
- autoload :Plugins, "merb-core/plugins"
14
- autoload :Rack, "merb-core/rack"
15
- autoload :RenderMixin, "merb-core/controller/mixins/render"
16
- autoload :Request, "merb-core/dispatch/request"
17
- autoload :Parse, "merb-core/dispatch/request_parsers.rb"
18
- autoload :ResponderMixin, "merb-core/controller/mixins/responder"
19
- autoload :Router, "merb-core/dispatch/router"
20
- autoload :Test, "merb-core/test"
21
- autoload :Worker, "merb-core/dispatch/worker"
23
+ autoload :Test, "merb-core/test"
22
24
  end
23
25
 
24
26
  # Require this rather than autoloading it so we can be sure the default template
25
27
  # gets registered
26
- require 'merb-core/core_ext'
27
- require "merb-core/controller/template"
28
- require "merb-core/controller/merb_controller"
29
28
 
30
29
  module Merb
31
30
  module InlineTemplates; end
@@ -92,622 +92,627 @@
92
92
  # <code>params[:action]</code> and <code>params[:controller]</code> have been deprecated as of
93
93
  # the 0.9.0 release. They are no longer set during dispatch, and
94
94
  # have been replaced by <code>action_name</code> and <code>controller_name</code> respectively.
95
- class Merb::AbstractController
96
- include Merb::RenderMixin
97
- include Merb::InlineTemplates
98
-
99
- class_inheritable_accessor :_layout, :_template_root, :template_roots
100
- class_inheritable_accessor :_before_filters, :_after_filters
101
- class_inheritable_accessor :_before_dispatch_callbacks, :_after_dispatch_callbacks
102
-
103
- cattr_accessor :_abstract_subclasses
104
-
105
- # :api: plugin
106
- attr_accessor :body, :action_name, :_benchmarks
107
- # :api: private
108
- attr_accessor :_thrown_content
109
-
110
- # Stub so content-type support in RenderMixin doesn't throw errors
111
- # :api: private
112
- attr_accessor :content_type
113
-
114
- FILTER_OPTIONS = [:only, :exclude, :if, :unless, :with]
115
-
116
- self._before_filters, self._after_filters = [], []
117
- self._before_dispatch_callbacks, self._after_dispatch_callbacks = [], []
118
-
119
- #---
120
- # We're using abstract_subclasses so that Merb::Controller can have its
121
- # own subclasses. We're using a Set so we don't have to worry about
122
- # uniqueness.
123
- self._abstract_subclasses = Set.new
124
-
125
- # ==== Returns
126
- # String:: The controller name in path form, e.g. "admin/items".
127
- # :api: public
128
- def self.controller_name() @controller_name ||= self.name.to_const_path end
129
-
130
- # ==== Returns
131
- # String:: The controller name in path form, e.g. "admin/items".
132
- #
133
- # :api: public
134
- def controller_name() self.class.controller_name end
95
+
96
+ module Merb
97
+ module InlineTemplates; end
135
98
 
136
- # This is called after the controller is instantiated to figure out where to
137
- # look for templates under the _template_root. Override this to define a new
138
- # structure for your app.
139
- #
140
- # ==== Parameters
141
- # context<~to_s>:: The controller context (the action or template name).
142
- # type<~to_s>:: The content type. Could be nil.
143
- # controller<~to_s>::
144
- # The name of the controller. Defaults to being called with the controller_name. Set t
145
- #
146
- #
147
- # ==== Returns
148
- # String::
149
- # Indicating where to look for the template for the current controller,
150
- # context, and content-type.
151
- #
152
- # ==== Notes
153
- # The type is irrelevant for controller-types that don't support
154
- # content-type negotiation, so we default to not include it in the
155
- # superclass.
156
- #
157
- # ==== Examples
158
- # def _template_location
159
- # "#{params[:controller]}.#{params[:action]}.#{content_type}"
160
- # end
161
- #
162
- # This would look for templates at controller.action.mime.type instead
163
- # of controller/action.mime.type
164
- #
165
- # :api: public
166
- # @overridable
167
- def _template_location(context, type, controller)
168
- controller ? "#{controller}/#{context}" : context
169
- end
99
+ class AbstractController
100
+ include Merb::RenderMixin
101
+ include Merb::InlineTemplates
170
102
 
171
- # The location to look for a template - override this method for particular behaviour.
172
- #
173
- # ==== Parameters
174
- # template<String>:: The absolute path to a template - without template extension.
175
- # type<~to_s>::
176
- # The mime-type of the template that will be rendered. Defaults to being called with nil.
177
- #
178
- # :api: public
179
- # @overridable
180
- def _absolute_template_location(template, type)
181
- template
182
- end
103
+ class_inheritable_accessor :_layout, :_template_root, :template_roots
104
+ class_inheritable_accessor :_before_filters, :_after_filters
105
+ class_inheritable_accessor :_before_dispatch_callbacks, :_after_dispatch_callbacks
183
106
 
184
- # Resets the template roots to the template root passed in.
185
- #
186
- # ==== Parameters
187
- # root<~to_s>::
188
- # The new path to set the template root to.
189
- #
190
- # :api: public
191
- def self._template_root=(root)
192
- @_template_root = root
193
- _reset_template_roots
194
- end
107
+ cattr_accessor :_abstract_subclasses
195
108
 
196
- # Reset the template root based on the @_template_root ivar.
197
- #
198
- # :api: private
199
- def self._reset_template_roots
200
- self.template_roots = [[self._template_root, :_template_location]]
201
- end
109
+ # :api: plugin
110
+ attr_accessor :body, :action_name, :_benchmarks
111
+ # :api: private
112
+ attr_accessor :_thrown_content
202
113
 
203
- # ==== Returns
204
- # roots<Array[Array]>::
205
- # Template roots as pairs of template root path and template location
206
- # method.
207
- #
208
- # :api: plugin
209
- def self._template_roots
210
- self.template_roots || _reset_template_roots
211
- end
114
+ # Stub so content-type support in RenderMixin doesn't throw errors
115
+ # :api: private
116
+ attr_accessor :content_type
212
117
 
213
- # ==== Parameters
214
- # roots<Array[Array]>::
215
- # Template roots as pairs of template root path and template location
216
- # method.
217
- #
218
- # :api: plugin
219
- def self._template_roots=(roots)
220
- self.template_roots = roots
221
- end
118
+ FILTER_OPTIONS = [:only, :exclude, :if, :unless, :with]
119
+
120
+ self._before_filters, self._after_filters = [], []
121
+ self._before_dispatch_callbacks, self._after_dispatch_callbacks = [], []
122
+
123
+ #---
124
+ # We're using abstract_subclasses so that Merb::Controller can have its
125
+ # own subclasses. We're using a Set so we don't have to worry about
126
+ # uniqueness.
127
+ self._abstract_subclasses = Set.new
128
+
129
+ # ==== Returns
130
+ # String:: The controller name in path form, e.g. "admin/items".
131
+ # :api: public
132
+ def self.controller_name() @controller_name ||= self.name.to_const_path end
133
+
134
+ # ==== Returns
135
+ # String:: The controller name in path form, e.g. "admin/items".
136
+ #
137
+ # :api: public
138
+ def controller_name() self.class.controller_name end
222
139
 
223
- # Returns the list of classes that have specifically subclassed AbstractController.
224
- # Does not include all decendents.
225
- #
226
- # ==== Returns
227
- # Set:: The subclasses.
228
- #
229
- # :api: private
230
- def self.subclasses_list() _abstract_subclasses end
140
+ # This is called after the controller is instantiated to figure out where to
141
+ # look for templates under the _template_root. Override this to define a new
142
+ # structure for your app.
143
+ #
144
+ # ==== Parameters
145
+ # context<~to_s>:: The controller context (the action or template name).
146
+ # type<~to_s>:: The content type. Could be nil.
147
+ # controller<~to_s>::
148
+ # The name of the controller. Defaults to being called with the controller_name. Set t
149
+ #
150
+ #
151
+ # ==== Returns
152
+ # String::
153
+ # Indicating where to look for the template for the current controller,
154
+ # context, and content-type.
155
+ #
156
+ # ==== Notes
157
+ # The type is irrelevant for controller-types that don't support
158
+ # content-type negotiation, so we default to not include it in the
159
+ # superclass.
160
+ #
161
+ # ==== Examples
162
+ # def _template_location
163
+ # "#{params[:controller]}.#{params[:action]}.#{content_type}"
164
+ # end
165
+ #
166
+ # This would look for templates at controller.action.mime.type instead
167
+ # of controller/action.mime.type
168
+ #
169
+ # :api: public
170
+ # @overridable
171
+ def _template_location(context, type, controller)
172
+ controller ? "#{controller}/#{context}" : context
173
+ end
174
+
175
+ # The location to look for a template - override this method for particular behaviour.
176
+ #
177
+ # ==== Parameters
178
+ # template<String>:: The absolute path to a template - without template extension.
179
+ # type<~to_s>::
180
+ # The mime-type of the template that will be rendered. Defaults to being called with nil.
181
+ #
182
+ # :api: public
183
+ # @overridable
184
+ def _absolute_template_location(template, type)
185
+ template
186
+ end
187
+
188
+ # Resets the template roots to the template root passed in.
189
+ #
190
+ # ==== Parameters
191
+ # root<~to_s>::
192
+ # The new path to set the template root to.
193
+ #
194
+ # :api: public
195
+ def self._template_root=(root)
196
+ @_template_root = root
197
+ _reset_template_roots
198
+ end
199
+
200
+ # Reset the template root based on the @_template_root ivar.
201
+ #
202
+ # :api: private
203
+ def self._reset_template_roots
204
+ self.template_roots = [[self._template_root, :_template_location]]
205
+ end
206
+
207
+ # ==== Returns
208
+ # roots<Array[Array]>::
209
+ # Template roots as pairs of template root path and template location
210
+ # method.
211
+ #
212
+ # :api: plugin
213
+ def self._template_roots
214
+ self.template_roots || _reset_template_roots
215
+ end
216
+
217
+ # ==== Parameters
218
+ # roots<Array[Array]>::
219
+ # Template roots as pairs of template root path and template location
220
+ # method.
221
+ #
222
+ # :api: plugin
223
+ def self._template_roots=(roots)
224
+ self.template_roots = roots
225
+ end
231
226
 
232
- # ==== Parameters
233
- # klass<Merb::AbstractController>::
234
- # The controller that is being inherited from Merb::AbstractController
235
- #
236
- # :api: private
237
- def self.inherited(klass)
238
- _abstract_subclasses << klass.to_s
239
- helper_module_name = klass.to_s =~ /^(#|Merb::)/ ? "#{klass}Helper" : "Merb::#{klass}Helper"
240
- Object.make_module helper_module_name
241
- klass.class_eval <<-HERE
242
- include Object.full_const_get("#{helper_module_name}") rescue nil
243
- HERE
244
- super
245
- end
227
+ # Returns the list of classes that have specifically subclassed AbstractController.
228
+ # Does not include all decendents.
229
+ #
230
+ # ==== Returns
231
+ # Set:: The subclasses.
232
+ #
233
+ # :api: private
234
+ def self.subclasses_list() _abstract_subclasses end
246
235
 
247
- # This will initialize the controller, it is designed to be overridden in subclasses (like MerbController)
248
- # ==== Parameters
249
- # *args:: The args are ignored in this class, but we need this so that subclassed initializes can have parameters
250
- #
251
- # :api: private
252
- def initialize(*args)
253
- @_benchmarks = {}
254
- @_caught_content = {}
255
- end
236
+ # ==== Parameters
237
+ # klass<Merb::AbstractController>::
238
+ # The controller that is being inherited from Merb::AbstractController
239
+ #
240
+ # :api: private
241
+ def self.inherited(klass)
242
+ _abstract_subclasses << klass.to_s
243
+ helper_module_name = klass.to_s =~ /^(#|Merb::)/ ? "#{klass}Helper" : "Merb::#{klass}Helper"
244
+ Object.make_module helper_module_name
245
+ klass.class_eval <<-HERE
246
+ include Object.full_const_get("#{helper_module_name}") rescue nil
247
+ HERE
248
+ super
249
+ end
256
250
 
257
- # This will dispatch the request, calling internal before/after dispatch callbacks.
258
- # If the return value of _call_filters is not :filter_chain_completed the action is not called, and the return from the filters is used instead.
259
- #
260
- # ==== Parameters
261
- # action<~to_s>::
262
- # The action to dispatch to. This will be #send'ed in _call_action.
263
- # Defaults to :to_s.
264
- #
265
- # ==== Returns
266
- # <~to_s>::
267
- # Returns the string that was returned from the action.
268
- #
269
- # ==== Raises
270
- # ArgumentError:: Invalid result caught from before filters.
271
- #
272
- # :api: plugin
273
- def _dispatch(action)
274
- self.action_name = action
275
- self._before_dispatch_callbacks.each { |cb| cb.call(self) }
276
-
277
- caught = catch(:halt) do
278
- start = Time.now
279
- result = _call_filters(_before_filters)
280
- @_benchmarks[:before_filters_time] = Time.now - start if _before_filters
281
- result
251
+ # This will initialize the controller, it is designed to be overridden in subclasses (like MerbController)
252
+ # ==== Parameters
253
+ # *args:: The args are ignored in this class, but we need this so that subclassed initializes can have parameters
254
+ #
255
+ # :api: private
256
+ def initialize(*args)
257
+ @_benchmarks = {}
258
+ @_caught_content = {}
282
259
  end
283
260
 
284
- @body = case caught
285
- when :filter_chain_completed then _call_action(action_name)
286
- when String then caught
287
- # return *something* if you throw halt with nothing
288
- when nil then "<html><body><h1>Filter Chain Halted!</h1></body></html>"
289
- when Symbol then __send__(caught)
290
- when Proc then self.instance_eval(&caught)
291
- else
292
- raise ArgumentError, "Threw :halt, #{caught}. Expected String, nil, Symbol, Proc."
293
- end
294
- start = Time.now
295
- _call_filters(_after_filters)
296
- @_benchmarks[:after_filters_time] = Time.now - start if _after_filters
261
+ # This will dispatch the request, calling internal before/after dispatch callbacks.
262
+ # If the return value of _call_filters is not :filter_chain_completed the action is not called, and the return from the filters is used instead.
263
+ #
264
+ # ==== Parameters
265
+ # action<~to_s>::
266
+ # The action to dispatch to. This will be #send'ed in _call_action.
267
+ # Defaults to :to_s.
268
+ #
269
+ # ==== Returns
270
+ # <~to_s>::
271
+ # Returns the string that was returned from the action.
272
+ #
273
+ # ==== Raises
274
+ # ArgumentError:: Invalid result caught from before filters.
275
+ #
276
+ # :api: plugin
277
+ def _dispatch(action)
278
+ self.action_name = action
279
+ self._before_dispatch_callbacks.each { |cb| cb.call(self) }
280
+
281
+ caught = catch(:halt) do
282
+ start = Time.now
283
+ result = _call_filters(_before_filters)
284
+ @_benchmarks[:before_filters_time] = Time.now - start if _before_filters
285
+ result
286
+ end
287
+
288
+ @body = case caught
289
+ when :filter_chain_completed then _call_action(action_name)
290
+ when String then caught
291
+ # return *something* if you throw halt with nothing
292
+ when nil then "<html><body><h1>Filter Chain Halted!</h1></body></html>"
293
+ when Symbol then __send__(caught)
294
+ when Proc then self.instance_eval(&caught)
295
+ else
296
+ raise ArgumentError, "Threw :halt, #{caught}. Expected String, nil, Symbol, Proc."
297
+ end
298
+ start = Time.now
299
+ _call_filters(_after_filters)
300
+ @_benchmarks[:after_filters_time] = Time.now - start if _after_filters
297
301
 
298
- self._after_dispatch_callbacks.each { |cb| cb.call(self) }
302
+ self._after_dispatch_callbacks.each { |cb| cb.call(self) }
299
303
 
300
- @body
301
- end
304
+ @body
305
+ end
302
306
 
303
- # This method exists to provide an overridable hook for ActionArgs. It uses #send to call the action method.
304
- #
305
- # ==== Parameters
306
- # action<~to_s>:: the action method to dispatch to
307
- #
308
- # :api: plugin
309
- # @overridable
310
- def _call_action(action)
311
- send(action)
312
- end
307
+ # This method exists to provide an overridable hook for ActionArgs. It uses #send to call the action method.
308
+ #
309
+ # ==== Parameters
310
+ # action<~to_s>:: the action method to dispatch to
311
+ #
312
+ # :api: plugin
313
+ # @overridable
314
+ def _call_action(action)
315
+ send(action)
316
+ end
313
317
 
314
- # Calls a filter chain.
315
- #
316
- # ==== Parameters
317
- # filter_set<Array[Filter]>::
318
- # A set of filters in the form [[:filter, rule], [:filter, rule]]
319
- #
320
- # ==== Returns
321
- # Symbol:: :filter_chain_completed.
322
- #
323
- # ==== Notes
324
- # Filter rules can be Symbols, Strings, or Procs.
325
- #
326
- # Symbols or Strings::
327
- # Call the method represented by the +Symbol+ or +String+.
328
- # Procs::
329
- # Execute the +Proc+, in the context of the controller (self will be the
330
- # controller)
331
- #
332
- # :api: private
333
- def _call_filters(filter_set)
334
- (filter_set || []).each do |filter, rule|
335
- if _call_filter_for_action?(rule, action_name) && _filter_condition_met?(rule)
336
- case filter
337
- when Symbol, String
338
- if rule.key?(:with)
339
- args = rule[:with]
340
- send(filter, *args)
341
- else
342
- send(filter)
318
+ # Calls a filter chain.
319
+ #
320
+ # ==== Parameters
321
+ # filter_set<Array[Filter]>::
322
+ # A set of filters in the form [[:filter, rule], [:filter, rule]]
323
+ #
324
+ # ==== Returns
325
+ # Symbol:: :filter_chain_completed.
326
+ #
327
+ # ==== Notes
328
+ # Filter rules can be Symbols, Strings, or Procs.
329
+ #
330
+ # Symbols or Strings::
331
+ # Call the method represented by the +Symbol+ or +String+.
332
+ # Procs::
333
+ # Execute the +Proc+, in the context of the controller (self will be the
334
+ # controller)
335
+ #
336
+ # :api: private
337
+ def _call_filters(filter_set)
338
+ (filter_set || []).each do |filter, rule|
339
+ if _call_filter_for_action?(rule, action_name) && _filter_condition_met?(rule)
340
+ case filter
341
+ when Symbol, String
342
+ if rule.key?(:with)
343
+ args = rule[:with]
344
+ send(filter, *args)
345
+ else
346
+ send(filter)
347
+ end
348
+ when Proc then self.instance_eval(&filter)
343
349
  end
344
- when Proc then self.instance_eval(&filter)
345
350
  end
346
351
  end
352
+ return :filter_chain_completed
347
353
  end
348
- return :filter_chain_completed
349
- end
350
354
 
351
- # Determine whether the filter should be called for the current action using :only and :exclude.
352
- #
353
- # ==== Parameters
354
- # rule<Hash>:: Rules for the filter (see below).
355
- # action_name<~to_s>:: The name of the action to be called.
356
- #
357
- # ==== Options (rule)
358
- # :only<Array>::
359
- # Optional list of actions to fire. If given, action_name must be a part of
360
- # it for this function to return true.
361
- # :exclude<Array>::
362
- # Optional list of actions not to fire. If given, action_name must not be a
363
- # part of it for this function to return true.
364
- #
365
- # ==== Returns
366
- # Boolean:: True if the action should be called.
367
- #
368
- # :api: private
369
- def _call_filter_for_action?(rule, action_name)
370
- # Both:
371
- # * no :only or the current action is in the :only list
372
- # * no :exclude or the current action is not in the :exclude list
373
- (!rule.key?(:only) || rule[:only].include?(action_name)) &&
374
- (!rule.key?(:exclude) || !rule[:exclude].include?(action_name))
375
- end
355
+ # Determine whether the filter should be called for the current action using :only and :exclude.
356
+ #
357
+ # ==== Parameters
358
+ # rule<Hash>:: Rules for the filter (see below).
359
+ # action_name<~to_s>:: The name of the action to be called.
360
+ #
361
+ # ==== Options (rule)
362
+ # :only<Array>::
363
+ # Optional list of actions to fire. If given, action_name must be a part of
364
+ # it for this function to return true.
365
+ # :exclude<Array>::
366
+ # Optional list of actions not to fire. If given, action_name must not be a
367
+ # part of it for this function to return true.
368
+ #
369
+ # ==== Returns
370
+ # Boolean:: True if the action should be called.
371
+ #
372
+ # :api: private
373
+ def _call_filter_for_action?(rule, action_name)
374
+ # Both:
375
+ # * no :only or the current action is in the :only list
376
+ # * no :exclude or the current action is not in the :exclude list
377
+ (!rule.key?(:only) || rule[:only].include?(action_name)) &&
378
+ (!rule.key?(:exclude) || !rule[:exclude].include?(action_name))
379
+ end
376
380
 
377
- # Determines whether the filter should be run based on the conditions passed (:if and :unless)
378
- #
379
- # ==== Parameters
380
- # rule<Hash>:: Rules for the filter (see below).
381
- #
382
- # ==== Options (rule)
383
- # :if<Array>:: Optional conditions that must be met for the filter to fire.
384
- # :unless<Array>::
385
- # Optional conditions that must not be met for the filter to fire.
386
- #
387
- # ==== Returns
388
- # Boolean:: True if the conditions are met.
389
- #
390
- # :api: private
391
- def _filter_condition_met?(rule)
392
- # Both:
393
- # * no :if or the if condition evaluates to true
394
- # * no :unless or the unless condition evaluates to false
395
- (!rule.key?(:if) || _evaluate_condition(rule[:if])) &&
396
- (!rule.key?(:unless) || ! _evaluate_condition(rule[:unless]))
397
- end
381
+ # Determines whether the filter should be run based on the conditions passed (:if and :unless)
382
+ #
383
+ # ==== Parameters
384
+ # rule<Hash>:: Rules for the filter (see below).
385
+ #
386
+ # ==== Options (rule)
387
+ # :if<Array>:: Optional conditions that must be met for the filter to fire.
388
+ # :unless<Array>::
389
+ # Optional conditions that must not be met for the filter to fire.
390
+ #
391
+ # ==== Returns
392
+ # Boolean:: True if the conditions are met.
393
+ #
394
+ # :api: private
395
+ def _filter_condition_met?(rule)
396
+ # Both:
397
+ # * no :if or the if condition evaluates to true
398
+ # * no :unless or the unless condition evaluates to false
399
+ (!rule.key?(:if) || _evaluate_condition(rule[:if])) &&
400
+ (!rule.key?(:unless) || ! _evaluate_condition(rule[:unless]))
401
+ end
398
402
 
399
- # Evaluates a filter condition (:if or :unless)
400
- #
401
- # ==== Parameters
402
- # condition<Symbol, Proc>:: The condition to evaluate.
403
- #
404
- # ==== Raises
405
- # ArgumentError:: condition not a Symbol or Proc.
406
- #
407
- # ==== Returns
408
- # Boolean:: True if the condition is met.
409
- #
410
- # ==== Alternatives
411
- # If condition is a symbol, it will be send'ed. If it is a Proc it will be
412
- # called directly with self as an argument.
413
- #
414
- # :api: private
415
- def _evaluate_condition(condition)
416
- case condition
417
- when Symbol then self.send(condition)
418
- when Proc then self.instance_eval(&condition)
419
- else
420
- raise ArgumentError,
421
- 'Filter condtions need to be either a Symbol or a Proc'
403
+ # Evaluates a filter condition (:if or :unless)
404
+ #
405
+ # ==== Parameters
406
+ # condition<Symbol, Proc>:: The condition to evaluate.
407
+ #
408
+ # ==== Raises
409
+ # ArgumentError:: condition not a Symbol or Proc.
410
+ #
411
+ # ==== Returns
412
+ # Boolean:: True if the condition is met.
413
+ #
414
+ # ==== Alternatives
415
+ # If condition is a symbol, it will be send'ed. If it is a Proc it will be
416
+ # called directly with self as an argument.
417
+ #
418
+ # :api: private
419
+ def _evaluate_condition(condition)
420
+ case condition
421
+ when Symbol then self.send(condition)
422
+ when Proc then self.instance_eval(&condition)
423
+ else
424
+ raise ArgumentError,
425
+ 'Filter condtions need to be either a Symbol or a Proc'
426
+ end
422
427
  end
423
- end
424
428
 
425
- # Adds a filter to the after filter chain
426
- # ==== Parameters
427
- # filter<Symbol, Proc>:: The filter to add. Defaults to nil.
428
- # opts<Hash>::
429
- # Filter options (see class documentation under <tt>Filter Options</tt>).
430
- # &block:: A block to use as a filter if filter is nil.
431
- #
432
- # ==== Notes
433
- # If the filter already exists, its options will be replaced with opts.;
434
- #
435
- # :api: public
436
- def self.after(filter = nil, opts = {}, &block)
437
- add_filter(self._after_filters, filter || block, opts)
438
- end
429
+ # Adds a filter to the after filter chain
430
+ # ==== Parameters
431
+ # filter<Symbol, Proc>:: The filter to add. Defaults to nil.
432
+ # opts<Hash>::
433
+ # Filter options (see class documentation under <tt>Filter Options</tt>).
434
+ # &block:: A block to use as a filter if filter is nil.
435
+ #
436
+ # ==== Notes
437
+ # If the filter already exists, its options will be replaced with opts.;
438
+ #
439
+ # :api: public
440
+ def self.after(filter = nil, opts = {}, &block)
441
+ add_filter(self._after_filters, filter || block, opts)
442
+ end
439
443
 
440
- # Adds a filter to the before filter chain.
441
- #
442
- # ==== Parameters
443
- # filter<Symbol, Proc>:: The filter to add. Defaults to nil.
444
- # opts<Hash>::
445
- # Filter options (see class documentation under <tt>Filter Options</tt>).
446
- # &block:: A block to use as a filter if filter is nil.
447
- #
448
- # ==== Notes
449
- # If the filter already exists, its options will be replaced with opts.
450
- #
451
- # :api: public
452
- def self.before(filter = nil, opts = {}, &block)
453
- add_filter(self._before_filters, filter || block, opts)
454
- end
444
+ # Adds a filter to the before filter chain.
445
+ #
446
+ # ==== Parameters
447
+ # filter<Symbol, Proc>:: The filter to add. Defaults to nil.
448
+ # opts<Hash>::
449
+ # Filter options (see class documentation under <tt>Filter Options</tt>).
450
+ # &block:: A block to use as a filter if filter is nil.
451
+ #
452
+ # ==== Notes
453
+ # If the filter already exists, its options will be replaced with opts.
454
+ #
455
+ # :api: public
456
+ def self.before(filter = nil, opts = {}, &block)
457
+ add_filter(self._before_filters, filter || block, opts)
458
+ end
455
459
 
456
- # Removes a filter from the after filter chain. This removes the
457
- # filter from the filter chain for the whole controller and does not
458
- # take any options.
459
- #
460
- # ==== Parameters
461
- # filter<Symbol, String>:: A filter name to skip.
462
- #
463
- # :api: public
464
- def self.skip_after(filter)
465
- skip_filter(self._after_filters, filter)
466
- end
460
+ # Removes a filter from the after filter chain. This removes the
461
+ # filter from the filter chain for the whole controller and does not
462
+ # take any options.
463
+ #
464
+ # ==== Parameters
465
+ # filter<Symbol, String>:: A filter name to skip.
466
+ #
467
+ # :api: public
468
+ def self.skip_after(filter)
469
+ skip_filter(self._after_filters, filter)
470
+ end
467
471
 
468
- # Removes a filter from the before filter chain. This removes the
469
- # filter from the filter chain for the whole controller and does not
470
- # take any options.
471
- #
472
- # ==== Parameters
473
- # filter<Symbol, String>:: A filter name to skip.
474
- #
475
- # :api: public
476
- def self.skip_before(filter)
477
- skip_filter(self._before_filters , filter)
478
- end
479
-
480
- # There are three possible ways to use this method. First, if you have a named route,
481
- # you can specify the route as the first parameter as a symbol and any paramters in a
482
- # hash. Second, you can generate the default route by just passing the params hash,
483
- # just passing the params hash. Finally, you can use the anonymous parameters. This
484
- # allows you to specify the parameters to a named route in the order they appear in the
485
- # router.
486
- #
487
- # ==== Parameters(Named Route)
488
- # name<Symbol>::
489
- # The name of the route.
490
- # args<Hash>::
491
- # Parameters for the route generation.
492
- #
493
- # ==== Parameters(Default Route)
494
- # args<Hash>::
495
- # Parameters for the route generation. This route will use the default route.
496
- #
497
- # ==== Parameters(Anonymous Parameters)
498
- # name<Symbol>::
499
- # The name of the route.
500
- # args<Array>::
501
- # An array of anonymous parameters to generate the route
502
- # with. These parameters are assigned to the route parameters
503
- # in the order that they are passed.
504
- #
505
- # ==== Returns
506
- # String:: The generated URL.
507
- #
508
- # ==== Examples
509
- # Named Route
510
- #
511
- # Merb::Router.prepare do
512
- # match("/articles/:title").to(:controller => :articles, :action => :show).name("articles")
513
- # end
514
- #
515
- # url(:articles, :title => "new_article")
516
- #
517
- # Default Route
518
- #
519
- # Merb::Router.prepare do
520
- # default_routes
521
- # end
522
- #
523
- # url(:controller => "articles", :action => "new")
524
- #
525
- # Anonymous Paramters
526
- #
527
- # Merb::Router.prepare do
528
- # match("/articles/:year/:month/:title").to(:controller => :articles, :action => :show).name("articles")
529
- # end
530
- #
531
- # url(:articles, 2008, 10, "test_article")
532
- #
533
- # :api: public
534
- def url(name, *args)
535
- args << {}
536
- Merb::Router.url(name, *args)
537
- end
472
+ # Removes a filter from the before filter chain. This removes the
473
+ # filter from the filter chain for the whole controller and does not
474
+ # take any options.
475
+ #
476
+ # ==== Parameters
477
+ # filter<Symbol, String>:: A filter name to skip.
478
+ #
479
+ # :api: public
480
+ def self.skip_before(filter)
481
+ skip_filter(self._before_filters , filter)
482
+ end
483
+
484
+ # There are three possible ways to use this method. First, if you have a named route,
485
+ # you can specify the route as the first parameter as a symbol and any paramters in a
486
+ # hash. Second, you can generate the default route by just passing the params hash,
487
+ # just passing the params hash. Finally, you can use the anonymous parameters. This
488
+ # allows you to specify the parameters to a named route in the order they appear in the
489
+ # router.
490
+ #
491
+ # ==== Parameters(Named Route)
492
+ # name<Symbol>::
493
+ # The name of the route.
494
+ # args<Hash>::
495
+ # Parameters for the route generation.
496
+ #
497
+ # ==== Parameters(Default Route)
498
+ # args<Hash>::
499
+ # Parameters for the route generation. This route will use the default route.
500
+ #
501
+ # ==== Parameters(Anonymous Parameters)
502
+ # name<Symbol>::
503
+ # The name of the route.
504
+ # args<Array>::
505
+ # An array of anonymous parameters to generate the route
506
+ # with. These parameters are assigned to the route parameters
507
+ # in the order that they are passed.
508
+ #
509
+ # ==== Returns
510
+ # String:: The generated URL.
511
+ #
512
+ # ==== Examples
513
+ # Named Route
514
+ #
515
+ # Merb::Router.prepare do
516
+ # match("/articles/:title").to(:controller => :articles, :action => :show).name("articles")
517
+ # end
518
+ #
519
+ # url(:articles, :title => "new_article")
520
+ #
521
+ # Default Route
522
+ #
523
+ # Merb::Router.prepare do
524
+ # default_routes
525
+ # end
526
+ #
527
+ # url(:controller => "articles", :action => "new")
528
+ #
529
+ # Anonymous Paramters
530
+ #
531
+ # Merb::Router.prepare do
532
+ # match("/articles/:year/:month/:title").to(:controller => :articles, :action => :show).name("articles")
533
+ # end
534
+ #
535
+ # url(:articles, 2008, 10, "test_article")
536
+ #
537
+ # :api: public
538
+ def url(name, *args)
539
+ args << {}
540
+ Merb::Router.url(name, *args)
541
+ end
538
542
 
539
- alias_method :relative_url, :url
540
-
541
- # Returns the absolute url including the passed protocol and host.
542
- #
543
- # This uses the same arguments as the url method, with added requirements
544
- # of protocol and host options.
545
- #
546
- # :api: public
547
- def absolute_url(*args)
548
- # FIXME: arrgh, why request.protocol returns http://?
549
- # :// is not part of protocol name
550
- options = extract_options_from_args!(args) || {}
551
- protocol = options.delete(:protocol)
552
- host = options.delete(:host)
543
+ alias_method :relative_url, :url
544
+
545
+ # Returns the absolute url including the passed protocol and host.
546
+ #
547
+ # This uses the same arguments as the url method, with added requirements
548
+ # of protocol and host options.
549
+ #
550
+ # :api: public
551
+ def absolute_url(*args)
552
+ # FIXME: arrgh, why request.protocol returns http://?
553
+ # :// is not part of protocol name
554
+ options = extract_options_from_args!(args) || {}
555
+ protocol = options.delete(:protocol)
556
+ host = options.delete(:host)
553
557
 
554
- raise ArgumentError, "The :protocol option must be specified" unless protocol
555
- raise ArgumentError, "The :host option must be specified" unless host
558
+ raise ArgumentError, "The :protocol option must be specified" unless protocol
559
+ raise ArgumentError, "The :host option must be specified" unless host
556
560
 
557
- args << options
561
+ args << options
558
562
 
559
- protocol + "://" + host + url(*args)
560
- end
563
+ protocol + "://" + host + url(*args)
564
+ end
561
565
 
562
- # Generates a URL for a single or nested resource.
563
- #
564
- # ==== Parameters
565
- # resources<Symbol,Object>:: The resources for which the URL
566
- # should be generated. These resources should be specified
567
- # in the router.rb file using #resources and #resource.
568
- #
569
- # options<Hash>:: Any extra parameters that are needed to
570
- # generate the URL.
571
- #
572
- # ==== Returns
573
- # String:: The generated URL.
574
- #
575
- # ==== Examples
576
- #
577
- # Merb::Router.prepare do
578
- # resources :users do
579
- # resources :comments
580
- # end
581
- # end
582
- #
583
- # resource(:users) # => /users
584
- # resource(@user) # => /users/10
585
- # resource(@user, :comments) # => /users/10/comments
586
- # resource(@user, @comment) # => /users/10/comments/15
587
- # resource(:users, :new) # => /users/new
588
- # resource(:@user, :edit) # => /users/10/edit
589
- #
590
- # :api: public
591
- def resource(*args)
592
- args << {}
593
- Merb::Router.resource(*args)
594
- end
595
-
596
- # Calls the capture method for the selected template engine.
597
- #
598
- # ==== Parameters
599
- # *args:: Arguments to pass to the block.
600
- # &block:: The block to call.
601
- #
602
- # ==== Returns
603
- # String:: The output of a template block or the return value of a non-template block converted to a string.
604
- #
605
- # :api: public
606
- def capture(*args, &block)
607
- ret = nil
608
-
609
- captured = send("capture_#{@_engine}", *args) do |*args|
610
- ret = yield *args
566
+ # Generates a URL for a single or nested resource.
567
+ #
568
+ # ==== Parameters
569
+ # resources<Symbol,Object>:: The resources for which the URL
570
+ # should be generated. These resources should be specified
571
+ # in the router.rb file using #resources and #resource.
572
+ #
573
+ # options<Hash>:: Any extra parameters that are needed to
574
+ # generate the URL.
575
+ #
576
+ # ==== Returns
577
+ # String:: The generated URL.
578
+ #
579
+ # ==== Examples
580
+ #
581
+ # Merb::Router.prepare do
582
+ # resources :users do
583
+ # resources :comments
584
+ # end
585
+ # end
586
+ #
587
+ # resource(:users) # => /users
588
+ # resource(@user) # => /users/10
589
+ # resource(@user, :comments) # => /users/10/comments
590
+ # resource(@user, @comment) # => /users/10/comments/15
591
+ # resource(:users, :new) # => /users/new
592
+ # resource(:@user, :edit) # => /users/10/edit
593
+ #
594
+ # :api: public
595
+ def resource(*args)
596
+ args << {}
597
+ Merb::Router.resource(*args)
611
598
  end
612
599
 
613
- # return captured value only if it is not empty
614
- captured.empty? ? ret.to_s : captured
615
- end
600
+ # Calls the capture method for the selected template engine.
601
+ #
602
+ # ==== Parameters
603
+ # *args:: Arguments to pass to the block.
604
+ # &block:: The block to call.
605
+ #
606
+ # ==== Returns
607
+ # String:: The output of a template block or the return value of a non-template block converted to a string.
608
+ #
609
+ # :api: public
610
+ def capture(*args, &block)
611
+ ret = nil
616
612
 
617
- # Calls the concatenate method for the selected template engine.
618
- #
619
- # ==== Parameters
620
- # str<String>:: The string to concatenate to the buffer.
621
- # binding<Binding>:: The binding to use for the buffer.
622
- #
623
- # :api: public
624
- def concat(str, binding)
625
- send("concat_#{@_engine}", str, binding)
626
- end
613
+ captured = send("capture_#{@_engine}", *args) do |*args|
614
+ ret = yield *args
615
+ end
616
+
617
+ # return captured value only if it is not empty
618
+ captured.empty? ? ret.to_s : captured
619
+ end
620
+
621
+ # Calls the concatenate method for the selected template engine.
622
+ #
623
+ # ==== Parameters
624
+ # str<String>:: The string to concatenate to the buffer.
625
+ # binding<Binding>:: The binding to use for the buffer.
626
+ #
627
+ # :api: public
628
+ def concat(str, binding)
629
+ send("concat_#{@_engine}", str, binding)
630
+ end
627
631
 
628
- private
629
- # adds a filter to the specified filter chain
630
- # ==== Parameters
631
- # filters<Array[Filter]>:: The filter chain that this should be added to.
632
- # filter<Filter>:: A filter that should be added.
633
- # opts<Hash>::
634
- # Filter options (see class documentation under <tt>Filter Options</tt>).
635
- #
636
- # ==== Raises
637
- # ArgumentError::
638
- # Both :only and :exclude, or :if and :unless given, if filter is not a
639
- # Symbol, String or Proc, or if an unknown option is passed.
640
- #
641
- # :api: private
642
- def self.add_filter(filters, filter, opts={})
643
- raise(ArgumentError,
644
- "You can specify either :only or :exclude but
645
- not both at the same time for the same filter.") if opts.key?(:only) && opts.key?(:exclude)
632
+ private
633
+ # adds a filter to the specified filter chain
634
+ # ==== Parameters
635
+ # filters<Array[Filter]>:: The filter chain that this should be added to.
636
+ # filter<Filter>:: A filter that should be added.
637
+ # opts<Hash>::
638
+ # Filter options (see class documentation under <tt>Filter Options</tt>).
639
+ #
640
+ # ==== Raises
641
+ # ArgumentError::
642
+ # Both :only and :exclude, or :if and :unless given, if filter is not a
643
+ # Symbol, String or Proc, or if an unknown option is passed.
644
+ #
645
+ # :api: private
646
+ def self.add_filter(filters, filter, opts={})
647
+ raise(ArgumentError,
648
+ "You can specify either :only or :exclude but
649
+ not both at the same time for the same filter.") if opts.key?(:only) && opts.key?(:exclude)
646
650
 
647
- raise(ArgumentError,
648
- "You can specify either :if or :unless but
649
- not both at the same time for the same filter.") if opts.key?(:if) && opts.key?(:unless)
651
+ raise(ArgumentError,
652
+ "You can specify either :if or :unless but
653
+ not both at the same time for the same filter.") if opts.key?(:if) && opts.key?(:unless)
650
654
 
651
- opts.each_key do |key| raise(ArgumentError,
652
- "You can only specify known filter options, #{key} is invalid.") unless FILTER_OPTIONS.include?(key)
653
- end
655
+ opts.each_key do |key| raise(ArgumentError,
656
+ "You can only specify known filter options, #{key} is invalid.") unless FILTER_OPTIONS.include?(key)
657
+ end
654
658
 
655
- opts = normalize_filters!(opts)
659
+ opts = normalize_filters!(opts)
656
660
 
657
- case filter
658
- when Proc
659
- # filters with procs created via class methods have identical signature
660
- # regardless if they handle content differently or not. So procs just
661
- # get appended
662
- filters << [filter, opts]
663
- when Symbol, String
664
- if existing_filter = filters.find {|f| f.first.to_s == filter.to_s}
665
- filters[ filters.index(existing_filter) ] = [filter, opts]
666
- else
661
+ case filter
662
+ when Proc
663
+ # filters with procs created via class methods have identical signature
664
+ # regardless if they handle content differently or not. So procs just
665
+ # get appended
667
666
  filters << [filter, opts]
667
+ when Symbol, String
668
+ if existing_filter = filters.find {|f| f.first.to_s == filter.to_s}
669
+ filters[ filters.index(existing_filter) ] = [filter, opts]
670
+ else
671
+ filters << [filter, opts]
672
+ end
673
+ else
674
+ raise(ArgumentError,
675
+ 'Filters need to be either a Symbol, String or a Proc'
676
+ )
668
677
  end
669
- else
670
- raise(ArgumentError,
671
- 'Filters need to be either a Symbol, String or a Proc'
672
- )
678
+ end
679
+
680
+ # Skip a filter that was previously added to the filter chain. Useful in
681
+ # inheritence hierarchies.
682
+ #
683
+ # ==== Parameters
684
+ # filters<Array[Filter]>:: The filter chain that this should be removed from.
685
+ # filter<Filter>:: A filter that should be removed.
686
+ #
687
+ # ==== Raises
688
+ # ArgumentError:: filter not Symbol or String.
689
+ #
690
+ # :api: private
691
+ def self.skip_filter(filters, filter)
692
+ raise(ArgumentError, 'You can only skip filters that have a String or Symbol name.') unless
693
+ [Symbol, String].include? filter.class
694
+
695
+ Merb.logger.warn("Filter #{filter} was not found in your filter chain.") unless
696
+ filters.reject! {|f| f.first.to_s[filter.to_s] }
673
697
  end
674
- end
675
-
676
- # Skip a filter that was previously added to the filter chain. Useful in
677
- # inheritence hierarchies.
678
- #
679
- # ==== Parameters
680
- # filters<Array[Filter]>:: The filter chain that this should be removed from.
681
- # filter<Filter>:: A filter that should be removed.
682
- #
683
- # ==== Raises
684
- # ArgumentError:: filter not Symbol or String.
685
- #
686
- # :api: private
687
- def self.skip_filter(filters, filter)
688
- raise(ArgumentError, 'You can only skip filters that have a String or Symbol name.') unless
689
- [Symbol, String].include? filter.class
690
-
691
- Merb.logger.warn("Filter #{filter} was not found in your filter chain.") unless
692
- filters.reject! {|f| f.first.to_s[filter.to_s] }
693
- end
694
698
 
695
- # Ensures that the passed in hash values are always arrays.
696
- #
697
- # ==== Parameters
698
- # opts<Hash>:: Options for the filters (see below).
699
- #
700
- # ==== Options (opts)
701
- # :only<Symbol, Array[Symbol]>:: A list of actions.
702
- # :exclude<Symbol, Array[Symbol]>:: A list of actions.
703
- #
704
- # ==== Examples
705
- # normalize_filters!(:only => :new) #=> {:only => [:new]}
706
- #
707
- # :api: public
708
- def self.normalize_filters!(opts={})
709
- opts[:only] = Array(opts[:only]).map {|x| x.to_s} if opts[:only]
710
- opts[:exclude] = Array(opts[:exclude]).map {|x| x.to_s} if opts[:exclude]
711
- return opts
699
+ # Ensures that the passed in hash values are always arrays.
700
+ #
701
+ # ==== Parameters
702
+ # opts<Hash>:: Options for the filters (see below).
703
+ #
704
+ # ==== Options (opts)
705
+ # :only<Symbol, Array[Symbol]>:: A list of actions.
706
+ # :exclude<Symbol, Array[Symbol]>:: A list of actions.
707
+ #
708
+ # ==== Examples
709
+ # normalize_filters!(:only => :new) #=> {:only => [:new]}
710
+ #
711
+ # :api: public
712
+ def self.normalize_filters!(opts={})
713
+ opts[:only] = Array(opts[:only]).map {|x| x.to_s} if opts[:only]
714
+ opts[:exclude] = Array(opts[:exclude]).map {|x| x.to_s} if opts[:exclude]
715
+ return opts
716
+ end
712
717
  end
713
- end
718
+ end