Class: Halcyon::Controller

Inherits:
Object
  • Object
show all
Includes:
Exceptions
Defined in:
lib/halcyon/controller.rb

Overview

The base controller providing methods application controllers will need.

Constant Summary

Constants included from Exceptions

Exceptions::HTTP_STATUS_CODES

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(env) ⇒ Controller

Sets the @env and @request instance variables, used by various helping methods.

+env+ the request environment details


16
17
18
19
# File 'lib/halcyon/controller.rb', line 16

def initialize(env)
  @env = env
  @request = Rack::Request.new(@env)
end

Instance Attribute Details

#cookiesObject

Returns the value of attribute cookies.



10
11
12
# File 'lib/halcyon/controller.rb', line 10

def cookies
  @cookies
end

#envObject

Returns the value of attribute env.



7
8
9
# File 'lib/halcyon/controller.rb', line 7

def env
  @env
end

#requestObject

Returns the value of attribute request.



8
9
10
# File 'lib/halcyon/controller.rb', line 8

def request
  @request
end

#sessionObject

Returns the value of attribute session.



9
10
11
# File 'lib/halcyon/controller.rb', line 9

def session
  @session
end

Class Method Details

._add_filter(where, method_or_filter, options, block) ⇒ Object

Used internally to save the filters, applied when called.



245
246
247
# File 'lib/halcyon/controller.rb', line 245

def _add_filter(where, method_or_filter, options, block)
  self.filters[where] << [method_or_filter, options, block]
end

.after(method_or_filter, options = {}, &block) ⇒ Object

See documentation for the before method.



239
240
241
# File 'lib/halcyon/controller.rb', line 239

def after method_or_filter, options={}, &block
  _add_filter(:after, method_or_filter, options, block)
end

.before(method_or_filter, options = {}, &block) ⇒ Object

Sets up filters for the method defined in the controllers.

Examples

class Foos < Application
  before :foo do
    #
  end
  after :blah, :only => [:foo]
  def foo
    # the block is called before the method is called
    # and the method is called after the method is called
  end
  private
  def blah
    #
  end
end

Options

  • method_or_filter either the method to run before



233
234
235
# File 'lib/halcyon/controller.rb', line 233

def before method_or_filter, options={}, &block
  _add_filter(:before, method_or_filter, options, block)
end

.controller_nameObject

Returns the name of the controller in path form.



84
85
86
# File 'lib/halcyon/controller.rb', line 84

def self.controller_name
  @controller_name ||= self.name.to_const_path
end

.filtersObject

Creates filters accessor method and initializes the @filters attribute with the necessary structure.



207
208
209
# File 'lib/halcyon/controller.rb', line 207

def filters
  @filters ||= {:before => [], :after => []}
end

Instance Method Details

#_dispatch(action) ⇒ Object

Used internally.

Dispatches the action specified, including all filters.



25
26
27
28
29
30
# File 'lib/halcyon/controller.rb', line 25

def _dispatch(action)
  _run_filters(:before, action)
  response = send(action)
  _run_filters(:after, action)
  response
end

#_filter_condition_met?(method_or_filter, options, action) ⇒ Boolean

Used internally.

Tests whether a filter should be run for an action or not.

Returns:

  • (Boolean)


273
274
275
276
277
278
279
280
# File 'lib/halcyon/controller.rb', line 273

def _filter_condition_met?(method_or_filter, options, action)
  (
    options[:only] and options[:only].include?(action)) or
    (options[:except] and !options[:except].include?(action)
  ) or (
    method_or_filter == action
  )
end

#_run_filters(where, action) ⇒ Object

Used internally.

Applies the filters defined by the before and after class methods.

where specifies whether to apply :before or :after

filters

action the routed action (for testing filter applicability)



259
260
261
262
263
264
265
266
267
# File 'lib/halcyon/controller.rb', line 259

def _run_filters(where, action)
  self.class.filters[where].each do |(method_or_filter, options, block)|
    if block
      block.call(self) if _filter_condition_met?(method_or_filter, options, action)
    else
      send(method_or_filter) if _filter_condition_met?(method_or_filter, options, action)
    end
  end
end

#controller_nameObject

Returns the name of the controller in path form.



90
91
92
# File 'lib/halcyon/controller.rb', line 90

def controller_name
  self.class.controller_name
end

#getObject

Returns any GET params, excluding POST and route params.

Returns Hash:….to_mash



52
53
54
# File 'lib/halcyon/controller.rb', line 52

def get
  self.request.GET.to_mash
end

#methodObject

The request method.

Returns Symbol:get|post|put|delete



78
79
80
# File 'lib/halcyon/controller.rb', line 78

def method
  self.env['REQUEST_METHOD'].downcase.to_sym
end

#not_found(body = 'Not Found', headers = {}) ⇒ Object Also known as: missing

Formats message into the standard response hash, with a status of 404 (the standard “Not Found” response value).

+body+ the body of the response

The body defaults to String:"Not Found" but can be anything, including hashes, arrays, and literal values. However, it is strongly discouraged since the body should simply describe the problem with processing their request.

Alternatively, if you choose to modify the message format, add a key in addition to :status and :body. For example: {:status=>404,:body=>'Not Found', :suggestions=>[...]}

Changes to this method described above should be reflected for in the clients as well.

Aliases

<tt>missing</tt>

Returns Hash::body=>body



193
194
195
# File 'lib/halcyon/controller.rb', line 193

def not_found(body='Not Found', headers = {})
  {:status => 404, :body => body, :headers => headers}
end

#ok(body = 'OK', headers = {}) ⇒ Object Also known as: success

Formats message into the standard success response hash, with a status of 200 (the standard success response).

+body+ the body of the response

The body defaults to String:"OK" but can be anything, including hashes, arrays, and literal values.

Alternatively, if you choose to modify the message format, add a key in addition to :status and :body. For example: {:status=>200,:body=>'OK', :stats=>[...], :receipt=>...}

Changes to this method described above should be reflected for in the clients as well.

Aliases

<tt>success</tt>

Returns Hash::body=>body



167
168
169
# File 'lib/halcyon/controller.rb', line 167

def ok(body='OK', headers = {})
  {:status => 200, :body => body, :headers => headers}
end

#paramsObject

Returns the request params and the route params.

Returns Hash:get_params, post_params.to_mash



36
37
38
# File 'lib/halcyon/controller.rb', line 36

def params
  self.request.params.merge(self.env['halcyon.route']).to_mash
end

#postObject

Returns any POST params, excluding GET and route params.

Returns Hash:….to_mash



44
45
46
# File 'lib/halcyon/controller.rb', line 44

def post
  self.request.POST.to_mash
end

#query_paramsObject

Returns query params (usually the GET params).

Returns Hash:….to_mash



60
61
62
# File 'lib/halcyon/controller.rb', line 60

def query_params
  Rack::Utils.parse_query(self.env['QUERY_STRING']).to_mash
end

#status(state, body = nil) ⇒ Object Also known as: error

Responds with the correct status and body specified.

  • state a snake-case symbol of the status (ie, :not_found, :unprocessable_entity, or :forbidden)

  • body the response body (if the default is insufficient)

Examples:

class Foos < Application
  def show
    if (foo = Foo[params[:id]])
      ok(foo)
    else
      status :not_found
    end
  end
end

The above example is the same as raise NotFound.new.

If the state specified is not found, it will raise ServiceUnavailable.new (a 503 error). The error is then logged along with the backtrace.



139
140
141
142
143
144
145
# File 'lib/halcyon/controller.rb', line 139

def status(state, body = nil)
  raise Halcyon::Exceptions.const_get(state.to_s.camel_case.to_sym).new(body)
rescue NameError => e
  self.logger.error "Invalid status #{state.inspect} specified."
  self.logger.error "Backtrace:\n" << e.backtrace.join("\n\t")
  raise Halcyon::Exceptions::ServiceUnavailable.new
end

#uriObject

The path of the request URL.

Returns String:/path/of/request



68
69
70
71
72
# File 'lib/halcyon/controller.rb', line 68

def uri
  # special parsing is done to remove the protocol, host, and port that
  # some Handlers leave in there. (Fixes inconsistencies.)
  URI.parse(self.env['REQUEST_URI'] || self.env['PATH_INFO']).path
end

#url(name, rparams = {}) ⇒ Object

Generates a URL based on the given name and passed options. Used with named routes and resources:

url(:users) # => "/users"
url(:admin_permissons) # => "/admin/permissions"
url(:user, @user) # => "/users/1"

Based on the identical method of Merb’s controller.



103
104
105
106
107
108
109
# File 'lib/halcyon/controller.rb', line 103

def url(name, rparams={})
  Halcyon::Application::Router.generate(name, rparams,
    { :controller => controller_name,
      :action => method
    }
  )
end