class Rory::Controller

Interface for Controller class. Subclass this to create controllers with actions that will be called by the Dispatcher when a route matches.

Attributes

dispatcher[R]
locals[RW]

Public Class Methods

after_action(method_name, opts = {}) click to toggle source

Register a method to run after the action method.

# File lib/rory/controller.rb, line 28
def after_action(method_name, opts = {})
  after_actions << opts.merge(:method_name => method_name)
end
after_actions() click to toggle source
# File lib/rory/controller.rb, line 18
def after_actions
  @after_actions ||= ancestor_actions(:after)
end
ancestor_actions(action_type) click to toggle source
# File lib/rory/controller.rb, line 32
def ancestor_actions(action_type)
  query_method = :"#{action_type}_actions"
  if superclass && superclass.respond_to?(query_method)
    superclass.send(query_method).flatten.compact
  else
    []
  end
end
before_action(method_name, opts = {}) click to toggle source

Register a method to run before the action method.

# File lib/rory/controller.rb, line 23
def before_action(method_name, opts = {})
  before_actions << opts.merge(:method_name => method_name)
end
before_actions() click to toggle source
# File lib/rory/controller.rb, line 14
def before_actions
  @before_actions ||= ancestor_actions(:before)
end
new(request, routing, app = nil) click to toggle source
# File lib/rory/controller.rb, line 42
def initialize(request, routing, app = nil)
  @request = request
  @dispatcher = routing[:dispatcher]
  @route = routing[:route]
  @params = request.params
  @app = app
  @locals = {}
end

Public Instance Methods

base_path() click to toggle source
# File lib/rory/controller.rb, line 74
def base_path
  @request.script_name
end
default_content_type(opts = {}) click to toggle source
# File lib/rory/controller.rb, line 139
def default_content_type(opts = {})
  if json_requested? || opts[:json]
    'application/json'
  else
    'text/html'
  end
end
default_renderer_options() click to toggle source
# File lib/rory/controller.rb, line 78
def default_renderer_options
  {
    :layout => layout,
    :locals => locals,
    :app => @app,
    :base_path => base_path
  }
end
expose(hsh) click to toggle source
# File lib/rory/controller.rb, line 55
def expose(hsh)
  locals.merge!(hsh)
end
extract_options(options_or_template, opts = {}) click to toggle source
# File lib/rory/controller.rb, line 87
def extract_options(options_or_template, opts = {})
  if options_or_template.is_a?(Hash)
    options_or_template
  else
    opts.merge(:template => options_or_template)
  end
end
generate_body_from_template(template_name, opts = {}) click to toggle source
# File lib/rory/controller.rb, line 125
def generate_body_from_template(template_name, opts = {})
  opts = default_renderer_options.merge(opts)
  renderer = Rory::Renderer.new(template_name, opts)
  renderer.render
end
generate_for_render(opts = {}) click to toggle source
# File lib/rory/controller.rb, line 115
def generate_for_render(opts = {})
  object, template = opts.delete(:json), opts.delete(:template)
  if object
    generate_json_from_object(object, opts)
  else
    template ||= route_template
    generate_body_from_template(template, opts)
  end
end
generate_json_from_object(object, opts = {}) click to toggle source
# File lib/rory/controller.rb, line 111
def generate_json_from_object(object, opts = {})
  Rory::Support.encode_as_json(object)
end
json_requested?() click to toggle source
# File lib/rory/controller.rb, line 51
def json_requested?
  dispatcher.json_requested?
end
layout() click to toggle source
# File lib/rory/controller.rb, line 70
def layout
  nil
end
params() click to toggle source
# File lib/rory/controller.rb, line 59
def params
  @converted_params ||= @params.inject({}) { |memo, (key, value)|
    memo[key.to_sym] = memo[key.to_s] = value
    memo
  }
end
present() click to toggle source
# File lib/rory/controller.rb, line 147
def present
  # Call all before and after filters, and if a method exists on the
  # controller for the requested action, call it in between.
  call_filtered_action(@route.action.to_sym)

  if @response
    # that method may have resulted in a response already being generated
    # (such as a redirect, or 404, or other non-HTML response).  if so,
    # just return that response.
    @response
  else
    # even if there wasn't a full response generated, we might already have
    # a @body, if @body was explicitly assigned for some reason.
    # don't render the default template, in that case.
    render(:body => @body)
  end
end
redirect(path) click to toggle source
# File lib/rory/controller.rb, line 131
def redirect(path)
  @response = dispatcher.redirect(path)
end
render(options_or_template = nil, opts = {}) click to toggle source
# File lib/rory/controller.rb, line 104
def render(options_or_template = nil, opts = {})
  opts = extract_options(options_or_template, opts)
  set_response_defaults(opts)
  opts[:body] ||= generate_for_render(opts)
  @response = [opts[:status], opts[:headers], [opts[:body]]]
end
render_not_found() click to toggle source
# File lib/rory/controller.rb, line 135
def render_not_found
  @response = dispatcher.render_not_found
end
route_template() click to toggle source
# File lib/rory/controller.rb, line 66
def route_template
  "#{@route.controller}/#{@route.action}"
end
set_response_defaults(opts) click to toggle source
# File lib/rory/controller.rb, line 95
def set_response_defaults(opts)
  opts[:content_type] ||= default_content_type(opts)
  opts[:status] ||= 200
  opts[:headers] = {
    'Content-type' => opts[:content_type],
    'charset' => 'UTF-8'
  }.merge(opts[:headers] || {})
end

Private Instance Methods

assess_filter_condition(condition) click to toggle source
# File lib/rory/controller.rb, line 185
def assess_filter_condition(condition)
  case condition
  when Symbol
    self.send(condition)
  when Proc
    instance_exec(&condition)
  end
end
call_filter_for_action?(filter, action) click to toggle source
# File lib/rory/controller.rb, line 167
def call_filter_for_action?(filter, action)
  (filter[:only].nil? || filter[:only].include?(action)) &&
    (filter[:except].nil? || !filter[:except].include?(action)) &&
    filter_conditions_pass?(filter, :if) &&
    filter_conditions_pass?(filter, :unless)
end
call_filter_set(which_set, action, opts = {}) click to toggle source
# File lib/rory/controller.rb, line 199
def call_filter_set(which_set, action, opts = {})
  opts = { :break_if_response => true }.merge(opts)
  filters = get_relevant_filters(which_set, action)
  filters.each do |filter|
    break if @response && opts[:break_if_response]
    self.send(filter[:method_name])
  end
end
call_filtered_action(action) click to toggle source
# File lib/rory/controller.rb, line 208
def call_filtered_action(action)
  call_filter_set(:before_actions, action)
  unless @response
    self.send(action) if self.respond_to?(action)
    call_filter_set(:after_actions, action, :break_if_response => false)
  end
end
filter_conditions_pass?(filter, type) click to toggle source
# File lib/rory/controller.rb, line 174
def filter_conditions_pass?(filter, type)
  filter_conditions = Array(filter[type])
  filter_conditions.compact.all? { |condition|
    result = assess_filter_condition(condition)
    if type == :unless
      result = !result
    end
    result
  }
end
get_relevant_filters(which_set, action) click to toggle source
# File lib/rory/controller.rb, line 194
def get_relevant_filters(which_set, action)
  filters = self.class.send(which_set)
  filters.select { |filter| call_filter_for_action?(filter, action) }
end