Class | Merb::AbstractController |
In: |
merb-core/lib/merb-core/controller/abstract_controller.rb
merb-helpers/lib/merb-helpers/form_helpers.rb |
Parent: | Object |
FILTER_OPTIONS | = | [:only, :exclude, :if, :unless, :with] |
_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 |
Reset the template root based on the @_template_root ivar.
:api: private
# 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.
root<~to_s>: | The new path to set the template root to. |
:api: public
# 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
Adds a filter to the after filter chain
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. |
If the filter already exists, its options will be replaced with opts.;
:api: public
# 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.
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. |
If the filter already exists, its options will be replaced with opts.
:api: public
# 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
klass<Merb::AbstractController>: | The controller that is being inherited from Merb::AbstractController |
:api: private
# 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)
*args: | The args are ignored in this class, but we need this so that subclassed initializes can have parameters |
:api: private
# 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.
filter<Symbol, String>: | A filter name to skip. |
:api: public
# 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.
filter<Symbol, String>: | A filter name to skip. |
:api: public
# 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.
Set: | The subclasses. |
:api: private
# File merb-core/lib/merb-core/controller/abstract_controller.rb, line 234 234: def self.subclasses_list() _abstract_subclasses end
adds a filter to the specified filter chain
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). |
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
# 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.
opts<Hash>: | Options for the filters (see below). |
:only<Symbol, Array[Symbol]>: | A list of actions. |
:exclude<Symbol, Array[Symbol]>: | A list of actions. |
normalize_filters!(:only => :new) #=> {:only => [:new]}
:api: public
# 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.
filters<Array[Filter]>: | The filter chain that this should be removed from. |
filter<Filter>: | A filter that should be removed. |
ArgumentError: | filter not Symbol or String. |
:api: private
# 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
The location to look for a template - override this method for particular behaviour.
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
# 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.
action<~to_s>: | the action method to dispatch to |
:api: plugin @overridable
# 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.
rule<Hash>: | Rules for the filter (see below). |
action_name<~to_s>: | The name of the action to be called. |
: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. |
Boolean: | True if the action should be called. |
:api: private
# 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.
filter_set<Array[Filter]>: | A set of filters in the form [[:filter, rule], [:filter, rule]] |
Symbol: | :filter_chain_completed. |
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
# 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.
action<~to_s>: | The action to dispatch to. This will be send‘ed in _call_action. Defaults to :to_s. |
<~to_s>: | Returns the string that was returned from the action. |
ArgumentError: | Invalid result caught from before filters. |
:api: plugin
# 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)
condition<Symbol, Proc>: | The condition to evaluate. |
ArgumentError: | condition not a Symbol or Proc. |
Boolean: | True if the condition is met. |
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
# 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)
rule<Hash>: | Rules for the filter (see below). |
: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. |
Boolean: | True if the conditions are met. |
:api: private
# 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.
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 |
String: | Indicating where to look for the template for the current controller, context, and content-type. |
The type is irrelevant for controller-types that don‘t support content-type negotiation, so we default to not include it in the superclass.
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
# 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
# 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.
*args: | Arguments to pass to the block. |
&block: | The block to call. |
String: | The output of a template block or the return value of a non-template block converted to a string. |
:api: public
# 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.
str<String>: | The string to concatenate to the buffer. |
binding<Binding>: | The binding to use for the buffer. |
:api: public
# 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
Generates a URL for a single or nested resource.
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.
String: | The generated URL. |
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
# 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.
name<Symbol>: | The name of the route. |
args<Hash>: | Parameters for the route generation. |
args<Hash>: | Parameters for the route generation. This route will use the default route. |
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. |
String: | The generated URL. |
Named Route
match("/articles/:title").to(:controller => :articles, :action => :show).name("articles")
end
url(:articles, :title => "new_article")
Default Route
default_routes
end
url(:controller => "articles", :action => "new")
Anonymous Paramters
match("/articles/:year/:month/:title").to(:controller => :articles, :action => :show).name("articles")
end
url(:articles, 2008, 10, "test_article")
:api: public
# 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