Class Merb::AbstractController
In: merb-core/lib/merb-core/controller/abstract_controller.rb
merb-helpers/lib/merb-helpers/form_helpers.rb
Parent: Object

Methods

Included Modules

Merb::RenderMixin Merb::InlineTemplates

Constants

FILTER_OPTIONS = [:only, :exclude, :if, :unless, :with]

Attributes

_benchmarks  [RW]  :api: plugin
_thrown_content  [RW]  :api: private
action_name  [RW]  :api: plugin
body  [RW]  :api: plugin
content_type  [RW]  Stub so content-type support in RenderMixin doesn‘t throw errors :api: private

Public Class methods

Reset the template root based on the @_template_root ivar.

:api: private

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 203
203:     def self._reset_template_roots
204:       self.template_roots = [[self._template_root, :_template_location]]
205:     end

Resets the template roots to the template root passed in.

Parameters

root<~to_s>:The new path to set the template root to.

:api: public

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 195
195:     def self._template_root=(root)
196:       @_template_root = root
197:       _reset_template_roots
198:     end

Returns

roots<Array[Array]>:Template roots as pairs of template root path and template location method.

:api: plugin

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 213
213:     def self._template_roots
214:       self.template_roots || _reset_template_roots
215:     end

Parameters

roots<Array[Array]>:Template roots as pairs of template root path and template location method.

:api: plugin

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 223
223:     def self._template_roots=(roots)
224:       self.template_roots = roots
225:     end

Adds a filter to the after filter chain

Parameters

filter<Symbol, Proc>:The filter to add. Defaults to nil.
opts<Hash>:Filter options (see class documentation under Filter Options).
&block:A block to use as a filter if filter is nil.

Notes

If the filter already exists, its options will be replaced with opts.;

:api: public

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 441
441:     def self.after(filter = nil, opts = {}, &block)
442:       add_filter(self._after_filters, filter || block, opts)
443:     end

Adds a filter to the before filter chain.

Parameters

filter<Symbol, Proc>:The filter to add. Defaults to nil.
opts<Hash>:Filter options (see class documentation under Filter Options).
&block:A block to use as a filter if filter is nil.

Notes

If the filter already exists, its options will be replaced with opts.

:api: public

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 457
457:     def self.before(filter = nil, opts = {}, &block)
458:       add_filter(self._before_filters, filter || block, opts)
459:     end

Returns

String:The controller name in path form, e.g. "admin/items".

:api: public

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 132
132:     def self.controller_name() @controller_name ||= self.name.to_const_path end

Parameters

klass<Merb::AbstractController>:The controller that is being inherited from Merb::AbstractController

:api: private

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 241
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 "include Object.full_const_get(\"\#{helper_module_name}\") rescue nil\n"
246:       super
247:     end

This will initialize the controller, it is designed to be overridden in subclasses (like MerbController)

Parameters

*args:The args are ignored in this class, but we need this so that subclassed initializes can have parameters

:api: private

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 257
257:     def initialize(*args)
258:       @_benchmarks = {}
259:       @_caught_content = {}
260:     end

Removes a filter from the after filter chain. This removes the filter from the filter chain for the whole controller and does not take any options.

Parameters

filter<Symbol, String>:A filter name to skip.

:api: public

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 469
469:     def self.skip_after(filter)
470:       skip_filter(self._after_filters, filter)
471:     end

Removes a filter from the before filter chain. This removes the filter from the filter chain for the whole controller and does not take any options.

Parameters

filter<Symbol, String>:A filter name to skip.

:api: public

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 481
481:     def self.skip_before(filter)
482:       skip_filter(self._before_filters , filter)
483:     end

Returns the list of classes that have specifically subclassed AbstractController. Does not include all decendents.

Returns

Set:The subclasses.

:api: private

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 234
234:     def self.subclasses_list() _abstract_subclasses end

Private Class methods

adds a filter to the specified filter chain

Parameters

filters<Array[Filter]>:The filter chain that this should be added to.
filter<Filter>:A filter that should be added.
opts<Hash>:Filter options (see class documentation under Filter Options).

Raises

ArgumentError:Both :only and :exclude, or :if and :unless given, if filter is not a Symbol, String or Proc, or if an unknown option is passed.

:api: private

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 647
647:     def self.add_filter(filters, filter, opts={})
648:       raise(ArgumentError,
649:         "You can specify either :only or :exclude but 
650:          not both at the same time for the same filter.") if opts.key?(:only) && opts.key?(:exclude)
651:        
652:        raise(ArgumentError,
653:          "You can specify either :if or :unless but 
654:           not both at the same time for the same filter.") if opts.key?(:if) && opts.key?(:unless)
655:         
656:       opts.each_key do |key| raise(ArgumentError,
657:         "You can only specify known filter options, #{key} is invalid.") unless FILTER_OPTIONS.include?(key)
658:       end
659: 
660:       opts = normalize_filters!(opts)
661:     
662:       case filter
663:       when Proc
664:         # filters with procs created via class methods have identical signature
665:         # regardless if they handle content differently or not. So procs just
666:         # get appended
667:         filters << [filter, opts]
668:       when Symbol, String
669:         if existing_filter = filters.find {|f| f.first.to_s == filter.to_s}
670:           filters[ filters.index(existing_filter) ] = [filter, opts]
671:         else
672:           filters << [filter, opts]
673:         end
674:       else
675:         raise(ArgumentError, 
676:           'Filters need to be either a Symbol, String or a Proc'
677:         )        
678:       end
679:     end

Ensures that the passed in hash values are always arrays.

Parameters

opts<Hash>:Options for the filters (see below).

Options (opts)

:only<Symbol, Array[Symbol]>:A list of actions.
:exclude<Symbol, Array[Symbol]>:A list of actions.

Examples

  normalize_filters!(:only => :new) #=> {:only => [:new]}

:api: public

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 713
713:     def self.normalize_filters!(opts={})
714:       opts[:only]     = Array(opts[:only]).map {|x| x.to_s} if opts[:only]
715:       opts[:exclude]  = Array(opts[:exclude]).map {|x| x.to_s} if opts[:exclude]
716:       return opts
717:     end

Skip a filter that was previously added to the filter chain. Useful in inheritence hierarchies.

Parameters

filters<Array[Filter]>:The filter chain that this should be removed from.
filter<Filter>:A filter that should be removed.

Raises

ArgumentError:filter not Symbol or String.

:api: private

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 692
692:     def self.skip_filter(filters, filter)
693:       raise(ArgumentError, 'You can only skip filters that have a String or Symbol name.') unless
694:         [Symbol, String].include? filter.class
695: 
696:       Merb.logger.warn("Filter #{filter} was not found in your filter chain.") unless
697:         filters.reject! {|f| f.first.to_s[filter.to_s] }
698:     end

Public Instance methods

The location to look for a template - override this method for particular behaviour.

Parameters

template<String>:The absolute path to a template - without template extension.
type<~to_s>:The mime-type of the template that will be rendered. Defaults to being called with nil.

:api: public @overridable

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 184
184:     def _absolute_template_location(template, type)
185:       template
186:     end

This method exists to provide an overridable hook for ActionArgs. It uses send to call the action method.

Parameters

action<~to_s>:the action method to dispatch to

:api: plugin @overridable

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 315
315:     def _call_action(action)
316:       send(action)
317:     end

Determine whether the filter should be called for the current action using :only and :exclude.

Parameters

rule<Hash>:Rules for the filter (see below).
action_name<~to_s>:The name of the action to be called.

Options (rule)

:only<Array>:Optional list of actions to fire. If given, action_name must be a part of it for this function to return true.
:exclude<Array>:Optional list of actions not to fire. If given, action_name must not be a part of it for this function to return true.

Returns

Boolean:True if the action should be called.

:api: private

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 374
374:     def _call_filter_for_action?(rule, action_name)
375:       # Both:
376:       # * no :only or the current action is in the :only list
377:       # * no :exclude or the current action is not in the :exclude list
378:       (!rule.key?(:only) || rule[:only].include?(action_name)) &&
379:       (!rule.key?(:exclude) || !rule[:exclude].include?(action_name))
380:     end

Calls a filter chain.

Parameters

filter_set<Array[Filter]>:A set of filters in the form [[:filter, rule], [:filter, rule]]

Returns

Symbol::filter_chain_completed.

Notes

Filter rules can be Symbols, Strings, or Procs.

Symbols or Strings:Call the method represented by the Symbol or String.
Procs:Execute the Proc, in the context of the controller (self will be the controller)

:api: private

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 338
338:     def _call_filters(filter_set)
339:       (filter_set || []).each do |filter, rule|
340:         if _call_filter_for_action?(rule, action_name) && _filter_condition_met?(rule)
341:           case filter
342:           when Symbol, String
343:             if rule.key?(:with)
344:               args = rule[:with]
345:               send(filter, *args)
346:             else
347:               send(filter)
348:             end
349:           when Proc then self.instance_eval(&filter)
350:           end
351:         end
352:       end
353:       return :filter_chain_completed
354:     end

This will dispatch the request, calling internal before/after dispatch callbacks. 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.

Parameters

action<~to_s>:The action to dispatch to. This will be send‘ed in _call_action. Defaults to :to_s.

Returns

<~to_s>:Returns the string that was returned from the action.

Raises

ArgumentError:Invalid result caught from before filters.

:api: plugin

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 278
278:     def _dispatch(action)
279:       self.action_name = action
280:       self._before_dispatch_callbacks.each { |cb| cb.call(self) }
281: 
282:       caught = catch(:halt) do
283:         start = Time.now
284:         result = _call_filters(_before_filters)
285:         @_benchmarks[:before_filters_time] = Time.now - start if _before_filters
286:         result
287:       end
288:   
289:       @body = case caught
290:       when :filter_chain_completed  then _call_action(action_name)
291:       when String                   then caught
292:       # return *something* if you throw halt with nothing
293:       when nil                      then "<html><body><h1>Filter Chain Halted!</h1></body></html>"
294:       when Symbol                   then __send__(caught)
295:       when Proc                     then self.instance_eval(&caught)
296:       else
297:         raise ArgumentError, "Threw :halt, #{caught}. Expected String, nil, Symbol, Proc."
298:       end
299:       start = Time.now
300:       _call_filters(_after_filters)
301:       @_benchmarks[:after_filters_time] = Time.now - start if _after_filters
302:     
303:       self._after_dispatch_callbacks.each { |cb| cb.call(self) }
304:     
305:       @body
306:     end

Evaluates a filter condition (:if or :unless)

Parameters

condition<Symbol, Proc>:The condition to evaluate.

Raises

ArgumentError:condition not a Symbol or Proc.

Returns

Boolean:True if the condition is met.

Alternatives

If condition is a symbol, it will be send‘ed. If it is a Proc it will be called directly with self as an argument.

:api: private

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 420
420:     def _evaluate_condition(condition)
421:       case condition
422:       when Symbol then self.send(condition)
423:       when Proc then self.instance_eval(&condition)
424:       else
425:         raise ArgumentError,
426:               'Filter condtions need to be either a Symbol or a Proc'
427:       end
428:     end

Determines whether the filter should be run based on the conditions passed (:if and :unless)

Parameters

rule<Hash>:Rules for the filter (see below).

Options (rule)

:if<Array>:Optional conditions that must be met for the filter to fire.
:unless<Array>:Optional conditions that must not be met for the filter to fire.

Returns

Boolean:True if the conditions are met.

:api: private

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 396
396:     def _filter_condition_met?(rule)
397:       # Both:
398:       # * no :if or the if condition evaluates to true
399:       # * no :unless or the unless condition evaluates to false
400:       (!rule.key?(:if) || _evaluate_condition(rule[:if])) &&
401:       (!rule.key?(:unless) || ! _evaluate_condition(rule[:unless]))
402:     end

This is called after the controller is instantiated to figure out where to look for templates under the _template_root. Override this to define a new structure for your app.

Parameters

context<~to_s>:The controller context (the action or template name).
type<~to_s>:The content type. Could be nil.
controller<~to_s>:The name of the controller. Defaults to being called with the controller_name. Set t

Returns

String:Indicating where to look for the template for the current controller, context, and content-type.

Notes

The type is irrelevant for controller-types that don‘t support content-type negotiation, so we default to not include it in the superclass.

Examples

  def _template_location
    "#{params[:controller]}.#{params[:action]}.#{content_type}"
  end

This would look for templates at controller.action.mime.type instead of controller/action.mime.type

:api: public @overridable

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 171
171:     def _template_location(context, type, controller)
172:       controller ? "#{controller}/#{context}" : context
173:     end

Returns the absolute url including the passed protocol and host.

This uses the same arguments as the url method, with added requirements of protocol and host options.

:api: public

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 552
552:     def absolute_url(*args)
553:       # FIXME: arrgh, why request.protocol returns http://?
554:       # :// is not part of protocol name
555:       options  = extract_options_from_args!(args) || {}
556:       protocol = options.delete(:protocol)
557:       host     = options.delete(:host)
558:     
559:       raise ArgumentError, "The :protocol option must be specified" unless protocol
560:       raise ArgumentError, "The :host option must be specified"     unless host
561:     
562:       args << options
563:     
564:       protocol + "://" + host + url(*args)
565:     end

Calls the capture method for the selected template engine.

Parameters

*args:Arguments to pass to the block.
&block:The block to call.

Returns

String:The output of a template block or the return value of a non-template block converted to a string.

:api: public

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 611
611:     def capture(*args, &block)
612:       ret = nil
613: 
614:       captured = send("capture_#{@_engine}", *args) do |*args|
615:         ret = yield *args
616:       end
617: 
618:       # return captured value only if it is not empty
619:       captured.empty? ? ret.to_s : captured
620:     end

Calls the concatenate method for the selected template engine.

Parameters

str<String>:The string to concatenate to the buffer.
binding<Binding>:The binding to use for the buffer.

:api: public

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 629
629:     def concat(str, binding)
630:       send("concat_#{@_engine}", str, binding)
631:     end

Returns

String:The controller name in path form, e.g. "admin/items".

:api: public

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 138
138:     def controller_name()      self.class.controller_name                   end
relative_url(name, *args)

Alias for url

Generates a URL for a single or nested resource.

Parameters

resources<Symbol,Object>:The resources for which the URL
  should be generated. These resources should be specified
  in the router.rb file using #resources and #resource.
options<Hash>:Any extra parameters that are needed to
  generate the URL.

Returns

String:The generated URL.

Examples

Merb::Router.prepare do

  resources :users do
    resources :comments
  end

end

resource(:users) # => /users resource(@user) # => /users/10 resource(@user, :comments) # => /users/10/comments resource(@user, @comment) # => /users/10/comments/15 resource(:users, :new) # => /users/new resource(:@user, :edit) # => /users/10/edit

:api: public

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 596
596:     def resource(*args)
597:       args << {}
598:       Merb::Router.resource(*args)
599:     end

There are three possible ways to use this method. First, if you have a named route, you can specify the route as the first parameter as a symbol and any paramters in a hash. Second, you can generate the default route by just passing the params hash, just passing the params hash. Finally, you can use the anonymous parameters. This allows you to specify the parameters to a named route in the order they appear in the router.

Parameters(Named Route)

name<Symbol>:The name of the route.
args<Hash>:Parameters for the route generation.

Parameters(Default Route)

args<Hash>:Parameters for the route generation. This route will use the default route.

Parameters(Anonymous Parameters)

name<Symbol>:The name of the route.
args<Array>:An array of anonymous parameters to generate the route with. These parameters are assigned to the route parameters in the order that they are passed.

Returns

String:The generated URL.

Examples

Named Route

Merb::Router.prepare do

  match("/articles/:title").to(:controller => :articles, :action => :show).name("articles")

end

url(:articles, :title => "new_article")

Default Route

Merb::Router.prepare do

  default_routes

end

url(:controller => "articles", :action => "new")

Anonymous Paramters

Merb::Router.prepare do

  match("/articles/:year/:month/:title").to(:controller => :articles, :action => :show).name("articles")

end

url(:articles, 2008, 10, "test_article")

:api: public

[Source]

     # File merb-core/lib/merb-core/controller/abstract_controller.rb, line 539
539:     def url(name, *args)
540:       args << {}
541:       Merb::Router.url(name, *args)
542:     end

[Validate]