rocketio 0.0.0 → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -5
- data/.pryrc +2 -0
- data/.travis.yml +3 -0
- data/README.md +22 -5
- data/Rakefile +7 -1
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/rocketio.rb +131 -3
- data/lib/rocketio/application.rb +31 -0
- data/lib/rocketio/controller.rb +288 -0
- data/lib/rocketio/controller/authentication.rb +141 -0
- data/lib/rocketio/controller/authorization.rb +53 -0
- data/lib/rocketio/controller/cookies.rb +59 -0
- data/lib/rocketio/controller/error_handlers.rb +89 -0
- data/lib/rocketio/controller/filters.rb +119 -0
- data/lib/rocketio/controller/flash.rb +21 -0
- data/lib/rocketio/controller/helpers.rb +438 -0
- data/lib/rocketio/controller/middleware.rb +32 -0
- data/lib/rocketio/controller/render.rb +148 -0
- data/lib/rocketio/controller/render/engine.rb +76 -0
- data/lib/rocketio/controller/render/layout.rb +27 -0
- data/lib/rocketio/controller/render/layouts.rb +85 -0
- data/lib/rocketio/controller/render/templates.rb +83 -0
- data/lib/rocketio/controller/request.rb +115 -0
- data/lib/rocketio/controller/response.rb +84 -0
- data/lib/rocketio/controller/sessions.rb +64 -0
- data/lib/rocketio/controller/token_auth.rb +118 -0
- data/lib/rocketio/controller/websocket.rb +21 -0
- data/lib/rocketio/error_templates/404.html +3 -0
- data/lib/rocketio/error_templates/409.html +7 -0
- data/lib/rocketio/error_templates/500.html +3 -0
- data/lib/rocketio/error_templates/501.html +6 -0
- data/lib/rocketio/error_templates/layout.html +1 -0
- data/lib/rocketio/exceptions.rb +4 -0
- data/lib/rocketio/router.rb +65 -0
- data/lib/rocketio/util.rb +122 -0
- data/lib/rocketio/version.rb +2 -2
- data/rocketio.gemspec +21 -17
- data/test/aliases_test.rb +54 -0
- data/test/authentication_test.rb +307 -0
- data/test/authorization_test.rb +91 -0
- data/test/cache_control_test.rb +268 -0
- data/test/content_type_test.rb +124 -0
- data/test/cookies_test.rb +49 -0
- data/test/error_handlers_test.rb +125 -0
- data/test/etag_test.rb +445 -0
- data/test/filters_test.rb +177 -0
- data/test/halt_test.rb +73 -0
- data/test/helpers_test.rb +171 -0
- data/test/middleware_test.rb +57 -0
- data/test/redirect_test.rb +135 -0
- data/test/render/engine_test.rb +71 -0
- data/test/render/get.erb +1 -0
- data/test/render/items.erb +1 -0
- data/test/render/layout.erb +1 -0
- data/test/render/layout_test.rb +104 -0
- data/test/render/layouts/master.erb +1 -0
- data/test/render/layouts_test.rb +145 -0
- data/test/render/master.erb +1 -0
- data/test/render/post.erb +1 -0
- data/test/render/put.erb +1 -0
- data/test/render/render_test.rb +101 -0
- data/test/render/setup.rb +14 -0
- data/test/render/templates/a/get.erb +1 -0
- data/test/render/templates/master.erb +1 -0
- data/test/render/templates_test.rb +146 -0
- data/test/request_test.rb +105 -0
- data/test/response_test.rb +119 -0
- data/test/routes_test.rb +70 -0
- data/test/sendfile_test.rb +209 -0
- data/test/sessions_test.rb +176 -0
- data/test/setup.rb +59 -0
- metadata +144 -9
- data/LICENSE.txt +0 -22
@@ -0,0 +1,141 @@
|
|
1
|
+
module RocketIO
|
2
|
+
class Controller
|
3
|
+
|
4
|
+
# easily restrict access to controller using basic auth
|
5
|
+
#
|
6
|
+
# @example protect all request methods
|
7
|
+
# basic_auth do |user,pass|
|
8
|
+
# user == 'admin' && pass == 'super secret password'
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# @example protect only POST, PUT and DELETE request methods
|
12
|
+
# basic_auth :post, :put, :delete do |user,pass|
|
13
|
+
# user == 'admin' && pass == 'super secret password'
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# @example use different credentials for GET and POST
|
17
|
+
# basic_auth :get do |user,pass|
|
18
|
+
# user == 'reader' && pass == 'readPass'
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# basic_auth :post do |user,pass|
|
22
|
+
# user == 'poster' && pass == 'writePass'
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# @note authorization is composable, that's it, if superclass is protecting :get method
|
26
|
+
# and current controller protects :post method,
|
27
|
+
# both :get and :post will be protected in current controller
|
28
|
+
#
|
29
|
+
# @params *args [Array]
|
30
|
+
# @param block [Proc]
|
31
|
+
#
|
32
|
+
def self.basic_auth *args, &block
|
33
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
34
|
+
rqms = args.any? ? args.map!(&:to_sym) : RocketIO::REQUEST_METHODS.values
|
35
|
+
rqms.each do |rm|
|
36
|
+
(@__basic_auth__ ||= {})[rm] = {
|
37
|
+
class: Rack::Auth::Basic,
|
38
|
+
arguments: [opts[:realm] || RocketIO::DEFAULT_AUTH_REALM].freeze,
|
39
|
+
block: block,
|
40
|
+
mock: RocketIO::HTTP_AUTHORIZATION_MOCKS[:basic]
|
41
|
+
}.freeze
|
42
|
+
end
|
43
|
+
define_basic_auth_methods
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.define_basic_auth_methods source = self
|
47
|
+
prompts = (source.instance_variable_get(:@__basic_auth__) || {}).each_with_object(allocate.basic_auth.dup) do |(rm,p),o|
|
48
|
+
method = :"__basic_auth__#{rm}__"
|
49
|
+
define_method(method, &p[:block])
|
50
|
+
o[rm] = p.merge(method: method).freeze
|
51
|
+
end.freeze
|
52
|
+
return if prompts.empty?
|
53
|
+
define_method(:basic_auth) {prompts}
|
54
|
+
end
|
55
|
+
|
56
|
+
def basic_auth; RocketIO::EMPTY_HASH end
|
57
|
+
|
58
|
+
# easily restrict access to controller using digest auth
|
59
|
+
#
|
60
|
+
# @example protect all request methods using hashed passwords
|
61
|
+
# # hash the password somewhere in irb:
|
62
|
+
# # ::Digest::MD5.hexdigest 'admin:AccessRestricted:somePassword'
|
63
|
+
# # username ^ realm ^ password ^
|
64
|
+
#
|
65
|
+
# #=> 9d77d54decc22cdcfb670b7b79ee0ef0
|
66
|
+
#
|
67
|
+
# digest_auth :passwords_hashed => true, :realm => 'AccessRestricted' do |user|
|
68
|
+
# {'admin' => '9d77d54decc22cdcfb670b7b79ee0ef0'}[user]
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# @example protect all request methods using plain passwords
|
72
|
+
# digest_auth do |user|
|
73
|
+
# {'admin' => 'password'}[user]
|
74
|
+
# end
|
75
|
+
#
|
76
|
+
# @example protect only POST, PUT and DELETE request methods
|
77
|
+
# digest_auth :post, :put, :delete do |user|
|
78
|
+
# {'admin' => 'password'}[user]
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
# @example use different credentials for GET and POST
|
82
|
+
# digest_auth :get do |user|
|
83
|
+
# {'user' => 'readPass'}[user]
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# digest_auth :post do |user|
|
87
|
+
# {'poster' => 'writePass'}[user]
|
88
|
+
# end
|
89
|
+
#
|
90
|
+
# @params *args [Array]
|
91
|
+
# @param block [Proc]
|
92
|
+
#
|
93
|
+
def self.digest_auth *args, &block
|
94
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
95
|
+
opts[:realm] ||= RocketIO::DEFAULT_AUTH_REALM
|
96
|
+
opts[:opaque] ||= opts[:realm]
|
97
|
+
rqms = args.any? ? args.map!(&:to_sym) : RocketIO::REQUEST_METHODS.values
|
98
|
+
rqms.each do |rm|
|
99
|
+
(@__digest_auth__ ||= {})[rm] = {
|
100
|
+
class: Rack::Auth::Digest::MD5,
|
101
|
+
arguments: [opts].freeze,
|
102
|
+
block: block,
|
103
|
+
mock: RocketIO::HTTP_AUTHORIZATION_MOCKS[:digest]
|
104
|
+
}.freeze
|
105
|
+
end
|
106
|
+
define_digest_auth_methods
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.define_digest_auth_methods source = self
|
110
|
+
prompts = (source.instance_variable_get(:@__digest_auth__) || {}).each_with_object(allocate.digest_auth.dup) do |(rm,p),o|
|
111
|
+
method = :"__digest_auth__#{rm}__"
|
112
|
+
define_method(method, &p[:block])
|
113
|
+
o[rm] = p.merge(method: method).freeze
|
114
|
+
end.freeze
|
115
|
+
return if prompts.empty?
|
116
|
+
define_method(:digest_auth) {prompts}
|
117
|
+
end
|
118
|
+
|
119
|
+
def digest_auth; RocketIO::EMPTY_HASH end
|
120
|
+
|
121
|
+
def user?
|
122
|
+
env[RocketIO::REMOTE_USER]
|
123
|
+
end
|
124
|
+
|
125
|
+
# checks whether authentication is required and
|
126
|
+
# send an authorization request if credentials not present or invalid
|
127
|
+
def validate_or_request_authentication_if_needed
|
128
|
+
return unless auth = digest_auth[requested_method] || basic_auth[requested_method]
|
129
|
+
return unless prompt = auth[:class].new(proc {}, *auth[:arguments]) do |*a|
|
130
|
+
self.__send__(auth[:method], *a)
|
131
|
+
end.call(
|
132
|
+
if RocketIO::HTTP_AUTHORIZATION_KEYS.detect {|key| env.has_key?(key)}
|
133
|
+
env
|
134
|
+
else
|
135
|
+
env.merge(RocketIO::HTTP_AUTHORIZATION_KEYS.first => auth[:mock])
|
136
|
+
end
|
137
|
+
)
|
138
|
+
throw(:__response__, prompt)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'rocketio/controller/token_auth'
|
2
|
+
|
3
|
+
module RocketIO
|
4
|
+
class Controller
|
5
|
+
|
6
|
+
# easily restrict access to controller using token auth
|
7
|
+
#
|
8
|
+
# @example simple Token example
|
9
|
+
#
|
10
|
+
# class User < RocketIO::Controller
|
11
|
+
# token_auth { |token| token == 'secret' }
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
def self.token_auth *args, &block
|
15
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
16
|
+
(args.any? ? args.map!(&:to_sym) : RocketIO::REQUEST_METHODS.values).each do |rm|
|
17
|
+
(@__token_auth__ ||= {})[rm] = {
|
18
|
+
realm: opts[:realm] || RocketIO::DEFAULT_TOKEN_AUTH_REALM.freeze,
|
19
|
+
block: block
|
20
|
+
}
|
21
|
+
end
|
22
|
+
define_token_auth_methods
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.define_token_auth_methods source = self
|
26
|
+
prompts = allocate.token_auth.merge(source.instance_variable_get(:@__token_auth__) || {}).freeze
|
27
|
+
return if prompts.empty?
|
28
|
+
define_method(:token_auth) {prompts}
|
29
|
+
end
|
30
|
+
|
31
|
+
def token_auth; RocketIO::EMPTY_HASH end
|
32
|
+
|
33
|
+
def validate_or_request_authorization_if_needed
|
34
|
+
return unless auth = token_auth[requested_method]
|
35
|
+
return if validate_token_auth(&auth[:block])
|
36
|
+
throw(:__response__, request_token_auth(auth[:realm]))
|
37
|
+
end
|
38
|
+
|
39
|
+
def validate_or_request_token_auth realm = RocketIO::DEFAULT_TOKEN_AUTH_REALM, &block
|
40
|
+
validate_token_auth(&block) || request_token_auth(realm)
|
41
|
+
end
|
42
|
+
|
43
|
+
def validate_token_auth &block
|
44
|
+
RocketIO::TokenAuth.authenticate(env, &block)
|
45
|
+
end
|
46
|
+
alias valid_token_auth? validate_token_auth
|
47
|
+
|
48
|
+
def request_token_auth realm = RocketIO::DEFAULT_TOKEN_AUTH_REALM
|
49
|
+
RocketIO::TokenAuth.authentication_request(realm)
|
50
|
+
end
|
51
|
+
alias request_token_auth! request_token_auth
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module RocketIO
|
2
|
+
class Controller
|
3
|
+
|
4
|
+
# shorthand for `request.cookies`, `response.set_cookie` and `response.delete_cookie`
|
5
|
+
#
|
6
|
+
# @example Setting a cookie
|
7
|
+
# cookies['cookie-name'] = 'value'
|
8
|
+
#
|
9
|
+
# @example Reading a cookie
|
10
|
+
# cookies['cookie-name']
|
11
|
+
#
|
12
|
+
# @example Setting a cookie with custom options
|
13
|
+
# cookies['question_of_the_day'] = {
|
14
|
+
# value: 'who is not who?',
|
15
|
+
# expires: Date.today + 1,
|
16
|
+
# secure: true
|
17
|
+
# }
|
18
|
+
#
|
19
|
+
# @example Deleting a cookie
|
20
|
+
# cookies.delete('cookie-name')
|
21
|
+
#
|
22
|
+
def cookies
|
23
|
+
@__cookies__ ||= RocketIO::Cookies.new(request.cookies, response)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
module RocketIO
|
29
|
+
class Cookies
|
30
|
+
|
31
|
+
def initialize cookies, response
|
32
|
+
@cookies = RocketIO.indifferent_params(cookies)
|
33
|
+
@response = response
|
34
|
+
end
|
35
|
+
|
36
|
+
# set cookie header
|
37
|
+
#
|
38
|
+
# @param [String, Symbol] key
|
39
|
+
# @param [String, Hash] val
|
40
|
+
#
|
41
|
+
def []= key, val
|
42
|
+
@response.set_cookie(key, val)
|
43
|
+
end
|
44
|
+
|
45
|
+
# get cookie by key
|
46
|
+
def [] key
|
47
|
+
@cookies[key]
|
48
|
+
end
|
49
|
+
|
50
|
+
# instruct browser to delete a cookie
|
51
|
+
#
|
52
|
+
# @param [String, Symbol] key
|
53
|
+
# @param [Hash] opts
|
54
|
+
#
|
55
|
+
def delete key, opts ={}
|
56
|
+
@response.delete_cookie(key, opts)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module RocketIO
|
2
|
+
class Controller
|
3
|
+
|
4
|
+
# define error handlers
|
5
|
+
#
|
6
|
+
# @example define a handler that will process 404 errors
|
7
|
+
# class Pages < RocketIO::Controller
|
8
|
+
#
|
9
|
+
# error 404 do |id|
|
10
|
+
# "Sorry, looks like item with ID #{id.to_i} does not exists"
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# def get id
|
14
|
+
# item = Item.find_by(id: id) || error(404, id)
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# @example define a handler that will process fatal errors
|
19
|
+
# class Pages < RocketIO::Controller
|
20
|
+
#
|
21
|
+
# error 500 do |exception|
|
22
|
+
# "Fatal error occurred: " + html_escape(exception.message)
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# def get
|
26
|
+
# # any exception raised here will be handled by the handler above
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
#
|
30
|
+
def self.error code, &block
|
31
|
+
code = code.to_i
|
32
|
+
code > 0 || raise(ArgumentError, 'Error code should be a number')
|
33
|
+
block || raise(ArgumentError, 'block missing')
|
34
|
+
(@__error_handlers__ ||= {})[code] = block
|
35
|
+
define_error_handlers_methods
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.define_error_handlers_methods source = self
|
39
|
+
handlers = (source.instance_variable_get(:@__error_handlers__) || {}).each_with_object({}) do |(code,proc),o|
|
40
|
+
o[code] = :"__#{code}_error_handler__"
|
41
|
+
define_method(o[code], &proc)
|
42
|
+
end
|
43
|
+
handlers.update(allocate.error_handlers)
|
44
|
+
return if handlers.empty?
|
45
|
+
handlers.freeze
|
46
|
+
define_method(:error_handlers) {handlers}
|
47
|
+
end
|
48
|
+
|
49
|
+
def error_handlers; RocketIO::EMPTY_HASH end
|
50
|
+
|
51
|
+
# if there is a handler defined for given code it will be executed and the result used as body.
|
52
|
+
# otherwise the `error` behaves exactly as `halt`.
|
53
|
+
#
|
54
|
+
# given args will be passed either to handler(if any defined) or to `halt`
|
55
|
+
#
|
56
|
+
def error code, *args
|
57
|
+
error_handlers[code] || halt(code, *args)
|
58
|
+
halt(code, __send__(error_handlers[code], *args))
|
59
|
+
end
|
60
|
+
alias error! error
|
61
|
+
|
62
|
+
# 404: Not Found
|
63
|
+
error 404 do
|
64
|
+
RocketIO.error_renderer(404, xhr?, env: env)
|
65
|
+
end
|
66
|
+
|
67
|
+
# 409: Wrong number of arguments received
|
68
|
+
error 409 do
|
69
|
+
RocketIO.error_renderer(409, xhr?, {
|
70
|
+
env: env,
|
71
|
+
controller: self.class,
|
72
|
+
resolved_path: url,
|
73
|
+
expected_parameters: parameters_policy[env[RocketIO::REQUEST_METHOD]],
|
74
|
+
received_parameters: path_params
|
75
|
+
})
|
76
|
+
end
|
77
|
+
|
78
|
+
# 500: Fatal Error
|
79
|
+
error 500 do |error|
|
80
|
+
error = StandardError.new(error) unless Exception === error
|
81
|
+
RocketIO.error_renderer(500, xhr?, env: env, error: error)
|
82
|
+
end
|
83
|
+
|
84
|
+
# 501: Not Implemented
|
85
|
+
error 501 do
|
86
|
+
RocketIO.error_renderer(501, xhr?, env: env)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module RocketIO
|
2
|
+
class Controller
|
3
|
+
|
4
|
+
# define blocks to run before, around, after called method.
|
5
|
+
# if no methods given, given block will run on any called method.
|
6
|
+
#
|
7
|
+
# @note call it without a block to define a void filter.
|
8
|
+
# useful to override inherited filters.
|
9
|
+
#
|
10
|
+
# @note sub-controllers will inherit all filters from parent controller
|
11
|
+
# and can override them selectively, by name
|
12
|
+
#
|
13
|
+
# @note wildcard filters will run before/around/after any methods,
|
14
|
+
# that's it, if defining `before {}` and `before(:get) {}` filters
|
15
|
+
# `get` method will run `before` filter then `before(:get)`
|
16
|
+
#
|
17
|
+
# @example run before any requested method, being it REST or websocket
|
18
|
+
# before do
|
19
|
+
# # some logic here
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# @example run only before GET
|
23
|
+
# before :get do
|
24
|
+
# # some logic here
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# @example run only around PUT and POST
|
28
|
+
# around :put, :post do |app|
|
29
|
+
# # some logic here
|
30
|
+
# app.call
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# @example run only after :register websocket call
|
34
|
+
# after :register do
|
35
|
+
# # some logic here
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# @example define a filter that does nothing. useful to override inherited filters.
|
39
|
+
# before :get
|
40
|
+
#
|
41
|
+
# @example run 2 blocks before GET
|
42
|
+
# before do # wildcard filter, will run before any method
|
43
|
+
# @user = User.find...
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# before :get do # named filter, will run only before `get`
|
47
|
+
# # wildcard filter already executed so we have `@user` variable here
|
48
|
+
# @photo = @user.photos.find...
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# # before calling `get` two filters will be executed:
|
52
|
+
# # - wildcard one
|
53
|
+
# # - named one
|
54
|
+
# def get
|
55
|
+
# # both @user and @photo variables available here
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
{
|
59
|
+
before: proc {},
|
60
|
+
around: proc {|app| app.call},
|
61
|
+
after: proc {}
|
62
|
+
}.each_pair do |filter,default_block|
|
63
|
+
define_methods = :"define_#{filter}_methods"
|
64
|
+
var = :"@__#{filter}_filters__"
|
65
|
+
|
66
|
+
define_singleton_method filter do |*methods,&block|
|
67
|
+
instance_variable_get(var) || instance_variable_set(var, {})
|
68
|
+
methods = [:*] if methods.empty?
|
69
|
+
methods.each do |meth|
|
70
|
+
instance_variable_get(var)[meth.to_sym] = block || default_block
|
71
|
+
end
|
72
|
+
__send__(define_methods)
|
73
|
+
end
|
74
|
+
|
75
|
+
define_singleton_method define_methods do |source = self|
|
76
|
+
filters = (source.instance_variable_get(var) || {}).each_with_object({}) do |(meth,proc),o|
|
77
|
+
o[meth] = :"__#{filter}_#{meth}__"
|
78
|
+
define_method(o[meth], &proc)
|
79
|
+
end
|
80
|
+
filters.update(allocate.__send__(filter))
|
81
|
+
return unless filters.any?
|
82
|
+
filters.freeze
|
83
|
+
define_method(filter) {filters}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def before; RocketIO::EMPTY_HASH end
|
88
|
+
def around; RocketIO::EMPTY_HASH end
|
89
|
+
def after; RocketIO::EMPTY_HASH end
|
90
|
+
|
91
|
+
def invoke_before_filter method = requested_method
|
92
|
+
__send__(before[:*]) if before[:*]
|
93
|
+
__send__(before[method]) if before[method]
|
94
|
+
end
|
95
|
+
|
96
|
+
# passing blocks somehow tends to add some overhead
|
97
|
+
# so passing the proc as a common argument
|
98
|
+
def invoke_around_filter method = requested_method, block
|
99
|
+
if around[:*]
|
100
|
+
__send__ around[:*], proc {
|
101
|
+
if around[method]
|
102
|
+
__send__(around[method], block)
|
103
|
+
else
|
104
|
+
block.call
|
105
|
+
end
|
106
|
+
}
|
107
|
+
elsif around[method]
|
108
|
+
__send__(around[method], block)
|
109
|
+
else
|
110
|
+
block.call
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def invoke_after_filter method = requested_method
|
115
|
+
__send__(after[:*]) if after[:*]
|
116
|
+
__send__(after[method]) if after[method]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|