halcyon 0.5.0 → 0.5.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.
- data/Rakefile +5 -0
- data/lib/halcyon.rb +42 -24
- data/lib/halcyon/application.rb +134 -45
- data/lib/halcyon/application/hooks.rb +38 -0
- data/lib/halcyon/config.rb +252 -0
- data/lib/halcyon/config/file.rb +100 -0
- data/lib/halcyon/config/helpers.rb +180 -0
- data/lib/halcyon/config/paths.rb +73 -0
- data/lib/halcyon/controller.rb +168 -38
- data/lib/halcyon/exceptions.rb +3 -2
- data/lib/halcyon/runner.rb +8 -99
- data/lib/halcyon/runner/commands.rb +3 -4
- data/lib/rack/jsonp.rb +38 -0
- data/spec/halcyon/application_spec.rb +9 -15
- data/spec/halcyon/config_spec.rb +157 -0
- data/spec/halcyon/controller_spec.rb +70 -11
- data/spec/halcyon/halcyon_spec.rb +8 -8
- data/spec/halcyon/router_spec.rb +3 -3
- data/spec/halcyon/runner_spec.rb +10 -26
- data/spec/spec_helper.rb +34 -8
- data/support/generators/halcyon/templates/config/init.rb +42 -0
- data/support/generators/halcyon_flat/templates/app.rb +5 -12
- metadata +17 -5
- data/support/generators/halcyon/templates/config/config.yml +0 -36
- data/support/generators/halcyon/templates/config/init/environment.rb +0 -11
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Halcyon
|
4
|
+
class Config
|
5
|
+
|
6
|
+
# Class to assist with loading configuration from a file.
|
7
|
+
#
|
8
|
+
# Examples:
|
9
|
+
#
|
10
|
+
# Halcyon::Config::File.new(file_name_or_path).to_hash #=> {...}
|
11
|
+
#
|
12
|
+
class File
|
13
|
+
|
14
|
+
attr_accessor :path
|
15
|
+
attr_accessor :content
|
16
|
+
|
17
|
+
# Creates a profile with the default paths.
|
18
|
+
#
|
19
|
+
# * +file+ is the path to the file.
|
20
|
+
# * +filter_config+ specifies whether to filter the contents through ERB
|
21
|
+
# before parsing it.
|
22
|
+
#
|
23
|
+
def initialize(file, filter_config = true)
|
24
|
+
if ::File.exist?(file)
|
25
|
+
self.path = file
|
26
|
+
elsif ::File.exist?(Halcyon.paths.for(:config)/file)
|
27
|
+
self.path = Halcyon.paths.for(:config)/file
|
28
|
+
else
|
29
|
+
raise ArgumentError.new("Could not find #{self.path} (it does not exist).")
|
30
|
+
end
|
31
|
+
self.content = self.filter(::File.read(self.path), filter_config)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Returns the loaded configuration file's contents parsed by the
|
35
|
+
# marshal format loader (defaulting to YAML, also providing JSON).
|
36
|
+
#
|
37
|
+
# Examples:
|
38
|
+
#
|
39
|
+
# p = Halcyon.paths.for(:config)/'config.yml'
|
40
|
+
# c = Halcyon::Config::File.new(p)
|
41
|
+
# c.to_hash #=> the contents of the config file parsed as YAML
|
42
|
+
# c.to_hash(:from_json) #=> same as above only parsed as JSON
|
43
|
+
# # parsing errors will happen if you try to use the wrong marshal
|
44
|
+
# # load method
|
45
|
+
#
|
46
|
+
def to_hash(from = :from_yaml)
|
47
|
+
case from
|
48
|
+
when :from_yaml
|
49
|
+
require 'yaml'
|
50
|
+
YAML.load(self.content)
|
51
|
+
when :from_json
|
52
|
+
JSON.parse(self.content)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Filters the contents through ERB.
|
57
|
+
#
|
58
|
+
def filter(content, filter_through_erb)
|
59
|
+
content = ERB.new(content).result if filter_through_erb
|
60
|
+
content
|
61
|
+
end
|
62
|
+
|
63
|
+
def inspect
|
64
|
+
"#<Halcyon::Config::File #{self.path}>"
|
65
|
+
end
|
66
|
+
|
67
|
+
class << self
|
68
|
+
|
69
|
+
# Provides a convenient way to load the configuration and return the
|
70
|
+
# appropriate hash contents.
|
71
|
+
#
|
72
|
+
def load(path)
|
73
|
+
file = File.new(path)
|
74
|
+
case path
|
75
|
+
when /\.(yaml|yml)/
|
76
|
+
file.to_hash
|
77
|
+
when /\.(json)/
|
78
|
+
file.to_hash(:from_json)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Loads the configuration file and parses it's contents as YAML.
|
83
|
+
# This is a shortcut method.
|
84
|
+
#
|
85
|
+
def load_from_yaml(path)
|
86
|
+
self.new(path).to_hash
|
87
|
+
end
|
88
|
+
|
89
|
+
# Loads the configuration file and parses it's contents as JSON.
|
90
|
+
# This is a shortcut method.
|
91
|
+
#
|
92
|
+
def load_from_json(path)
|
93
|
+
self.new(path).to_hash(:from_json)
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
module Halcyon
|
2
|
+
class Config
|
3
|
+
module Helpers
|
4
|
+
|
5
|
+
# Extends the target class with the Configurable and Accessors helpers.
|
6
|
+
def self.included(target)
|
7
|
+
target.extend(Configurable)
|
8
|
+
target.extend(Accessors)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Provides several convenience accessors for configuration values,
|
12
|
+
# including these:
|
13
|
+
# * <tt>app</tt>: the app name
|
14
|
+
# * <tt>root</tt>: the application working directory
|
15
|
+
# * <tt>db</tt>: database configuration settings
|
16
|
+
#
|
17
|
+
module Accessors
|
18
|
+
|
19
|
+
# Accesses the <tt>app</tt> config value which is the constantized
|
20
|
+
# version of the application name (which can be set manually in the
|
21
|
+
# config file as <tt>app: NameOfApp</tt>, defaulting to a camel case
|
22
|
+
# version of the application directory name).
|
23
|
+
#
|
24
|
+
def app
|
25
|
+
self.config[:app] || ::File.dirname(self.root).camel_case
|
26
|
+
end
|
27
|
+
|
28
|
+
# Sets the application name.
|
29
|
+
#
|
30
|
+
def app=(name)
|
31
|
+
self.config[:app] = name
|
32
|
+
end
|
33
|
+
|
34
|
+
# Accesses the <tt>root</tt> config value which is the root of the
|
35
|
+
# current Halcyon application (usually <tt>Dir.pwd</tt>).
|
36
|
+
#
|
37
|
+
# Defaults to <tt>Dir.pwd</tt>
|
38
|
+
#
|
39
|
+
def root
|
40
|
+
self.config[:root] || Dir.pwd rescue Dir.pwd
|
41
|
+
end
|
42
|
+
|
43
|
+
# Sets the application root.
|
44
|
+
#
|
45
|
+
def root=(path)
|
46
|
+
self.config[:root] = path
|
47
|
+
end
|
48
|
+
|
49
|
+
# Accesses the <tt>db</tt> config value. Intended to contain the
|
50
|
+
# database configuration values for whichever ORM is used.
|
51
|
+
#
|
52
|
+
def db
|
53
|
+
self.config[:db]
|
54
|
+
end
|
55
|
+
|
56
|
+
# Sets the database settings.
|
57
|
+
#
|
58
|
+
def db=(config)
|
59
|
+
self.config[:db] = config
|
60
|
+
end
|
61
|
+
|
62
|
+
# Accesses the <tt>environment</tt> config value. Intended to contain
|
63
|
+
# the environment the application is running in.
|
64
|
+
#
|
65
|
+
# Defaults to the <tt>development</tt> environment.
|
66
|
+
#
|
67
|
+
def environment
|
68
|
+
self.config[:environment] || :development
|
69
|
+
end
|
70
|
+
alias_method :env, :environment
|
71
|
+
|
72
|
+
# Sets the environment config value.
|
73
|
+
#
|
74
|
+
def environment=(env)
|
75
|
+
self.config[:environment] = env.to_sym
|
76
|
+
end
|
77
|
+
alias_method :env=, :environment=
|
78
|
+
|
79
|
+
# Provides a proxy to the Halcyon::Config::Paths instance.
|
80
|
+
#
|
81
|
+
def paths
|
82
|
+
self.config[:paths]
|
83
|
+
end
|
84
|
+
|
85
|
+
# Provides a proxy to the hooks hash.
|
86
|
+
#
|
87
|
+
def hooks
|
88
|
+
self.config[:hooks]
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
# Provides dynamic creation of configuration attribute accessors.
|
94
|
+
#
|
95
|
+
module Configurable
|
96
|
+
|
97
|
+
# Defines a dynamic accessor for configuration attributes.
|
98
|
+
#
|
99
|
+
# Examples:
|
100
|
+
#
|
101
|
+
# Halcyon.configurable(:db)
|
102
|
+
# Halcyon.db = {...}
|
103
|
+
# Halcyon.config[:db] #=> {...}
|
104
|
+
# Halcyon.config[:db] = true
|
105
|
+
# Halcyon.db #=> true
|
106
|
+
#
|
107
|
+
def configurable(attribute)
|
108
|
+
eval <<-"end;"
|
109
|
+
def #{attribute.to_s}
|
110
|
+
Halcyon.config[:#{attribute.to_s}]
|
111
|
+
end
|
112
|
+
def #{attribute.to_s}=(value)
|
113
|
+
value = value.to_mash if value.is_a?(Hash)
|
114
|
+
Halcyon.config[:#{attribute.to_s}] = value
|
115
|
+
end
|
116
|
+
end;
|
117
|
+
end
|
118
|
+
alias_method :configurable_attr, :configurable
|
119
|
+
|
120
|
+
# Defines a dynamic reader for configuration attributes, accepting
|
121
|
+
# either a string or a block to perform the action.
|
122
|
+
#
|
123
|
+
# Examples:
|
124
|
+
#
|
125
|
+
# Halcyon.configurable_reader(:foo) do
|
126
|
+
# self.config[:foo].to_sym
|
127
|
+
# end
|
128
|
+
#
|
129
|
+
# OR
|
130
|
+
#
|
131
|
+
# Halcyon.configurable_reader(:foo, "Halcyon.config[%s].to_sym")
|
132
|
+
#
|
133
|
+
def configurable_reader(attribute, code=nil, &block)
|
134
|
+
if block_given? and not code
|
135
|
+
Halcyon.class.send(:define_method, attribute.to_sym, block)
|
136
|
+
elsif code and not block_given?
|
137
|
+
Halcyon.class.send(:eval, <<-"end;")
|
138
|
+
def #{attribute.to_s}
|
139
|
+
#{code % [attribute.to_sym.inspect]}
|
140
|
+
end
|
141
|
+
end;
|
142
|
+
else
|
143
|
+
raise ArgumentError.new("Either a block or a code string should be supplied.")
|
144
|
+
end
|
145
|
+
end
|
146
|
+
alias_method :configurable_attr_reader, :configurable_reader
|
147
|
+
|
148
|
+
# Defines a dynamic writer for configuration attributes, accepting
|
149
|
+
# either a string or a block to perform the action.
|
150
|
+
#
|
151
|
+
# Examples:
|
152
|
+
#
|
153
|
+
# Halcyon.configurable_writer(:foo) do |val|
|
154
|
+
# self.config[:foo] = val.to_sym
|
155
|
+
# end
|
156
|
+
#
|
157
|
+
# OR
|
158
|
+
#
|
159
|
+
# Halcyon.configurable_reader(:foo, "Halcyon.config[%s] = value.to_sym")
|
160
|
+
#
|
161
|
+
def configurable_writer(attribute, code=nil, &block)
|
162
|
+
if block_given? and not code
|
163
|
+
Halcyon.class.send(:define_method, :"#{attribute}=", block)
|
164
|
+
elsif code and not block_given?
|
165
|
+
Halcyon.class.send(:eval, <<-"end;")
|
166
|
+
def #{attribute.to_s}=(value)
|
167
|
+
#{code % [attribute.to_sym.inspect]}
|
168
|
+
end
|
169
|
+
end;
|
170
|
+
else
|
171
|
+
raise ArgumentError.new("Either a block or a code string should be supplied.")
|
172
|
+
end
|
173
|
+
end
|
174
|
+
alias_method :configurable_attr_writer, :configurable_writer
|
175
|
+
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Halcyon
|
2
|
+
class Config
|
3
|
+
class Paths
|
4
|
+
|
5
|
+
attr_accessor :paths
|
6
|
+
|
7
|
+
# Creates a profile with the default paths.
|
8
|
+
def initialize(paths={})
|
9
|
+
self.paths = Mash.new(self.defaults.merge(paths))
|
10
|
+
end
|
11
|
+
|
12
|
+
# Gets the path for the specified entity.
|
13
|
+
#
|
14
|
+
# Examples:
|
15
|
+
#
|
16
|
+
# Halcyon.paths.for(:log) #=> "/path/to/app/log/"
|
17
|
+
#
|
18
|
+
def for(key)
|
19
|
+
self.paths[key] or raise ArgumentError.new("Path is not defined")
|
20
|
+
end
|
21
|
+
|
22
|
+
# Alias to <tt>for</tt>.
|
23
|
+
#
|
24
|
+
def [](key)
|
25
|
+
self.for(key)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Defines a path for the specified entity.
|
29
|
+
#
|
30
|
+
# Examples:
|
31
|
+
#
|
32
|
+
# Halcyon.paths.define(:tmp, Halcyon.root/'tmp')
|
33
|
+
#
|
34
|
+
# OR
|
35
|
+
#
|
36
|
+
# Halcyon.paths.define(:tmp => Halcyon.root/'tmp')
|
37
|
+
#
|
38
|
+
def define(key_or_hash, value = nil)
|
39
|
+
if key_or_hash.is_a?(Hash) and value.nil?
|
40
|
+
key_or_hash.keys.each do |key|
|
41
|
+
self.define(key, key_or_hash[key])
|
42
|
+
end
|
43
|
+
else
|
44
|
+
self.paths[key_or_hash] = value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Alias for <tt>define</tt>.
|
49
|
+
#
|
50
|
+
def []=(key, value)
|
51
|
+
self.define(key, value)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Default paths.
|
55
|
+
#
|
56
|
+
def defaults
|
57
|
+
{
|
58
|
+
:controller => Halcyon.root/'app',
|
59
|
+
:model => Halcyon.root/'app'/'models',
|
60
|
+
:lib => Halcyon.root/'lib',
|
61
|
+
:config => Halcyon.root/'config',
|
62
|
+
:init => Halcyon.root/'config'/'init',
|
63
|
+
:log => Halcyon.root/'log'
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
def inspect
|
68
|
+
"#<Halcyon::Config::Paths #{self.paths.keys.join(', ')}>"
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/halcyon/controller.rb
CHANGED
@@ -12,28 +12,27 @@ module Halcyon
|
|
12
12
|
# Sets the <tt>@env</tt> and <tt>@request</tt> instance variables, used by
|
13
13
|
# various helping methods.
|
14
14
|
# +env+ the request environment details
|
15
|
+
#
|
15
16
|
def initialize(env)
|
16
17
|
@env = env
|
17
18
|
@request = Rack::Request.new(@env)
|
18
19
|
end
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
raise NotImplemented.new
|
30
|
-
end
|
31
|
-
|
21
|
+
# Used internally.
|
22
|
+
#
|
23
|
+
# Dispatches the action specified, including all filters.
|
24
|
+
#
|
25
|
+
def _dispatch(action)
|
26
|
+
_run_filters(:before, action)
|
27
|
+
response = send(action)
|
28
|
+
_run_filters(:after, action)
|
29
|
+
response
|
32
30
|
end
|
33
31
|
|
34
32
|
# Returns the request params and the route params.
|
35
33
|
#
|
36
34
|
# Returns Hash:{route_params, get_params, post_params}.to_mash
|
35
|
+
#
|
37
36
|
def params
|
38
37
|
self.request.params.merge(self.env['halcyon.route']).to_mash
|
39
38
|
end
|
@@ -41,6 +40,7 @@ module Halcyon
|
|
41
40
|
# Returns any POST params, excluding GET and route params.
|
42
41
|
#
|
43
42
|
# Returns Hash:{...}.to_mash
|
43
|
+
#
|
44
44
|
def post
|
45
45
|
self.request.POST.to_mash
|
46
46
|
end
|
@@ -48,6 +48,7 @@ module Halcyon
|
|
48
48
|
# Returns any GET params, excluding POST and route params.
|
49
49
|
#
|
50
50
|
# Returns Hash:{...}.to_mash
|
51
|
+
#
|
51
52
|
def get
|
52
53
|
self.request.GET.to_mash
|
53
54
|
end
|
@@ -55,6 +56,7 @@ module Halcyon
|
|
55
56
|
# Returns query params (usually the GET params).
|
56
57
|
#
|
57
58
|
# Returns Hash:{...}.to_mash
|
59
|
+
#
|
58
60
|
def query_params
|
59
61
|
Rack::Utils.parse_query(self.env['QUERY_STRING']).to_mash
|
60
62
|
end
|
@@ -62,6 +64,7 @@ module Halcyon
|
|
62
64
|
# The path of the request URL.
|
63
65
|
#
|
64
66
|
# Returns String:/path/of/request
|
67
|
+
#
|
65
68
|
def uri
|
66
69
|
# special parsing is done to remove the protocol, host, and port that
|
67
70
|
# some Handlers leave in there. (Fixes inconsistencies.)
|
@@ -71,10 +74,77 @@ module Halcyon
|
|
71
74
|
# The request method.
|
72
75
|
#
|
73
76
|
# Returns Symbol:get|post|put|delete
|
77
|
+
#
|
74
78
|
def method
|
75
79
|
self.env['REQUEST_METHOD'].downcase.to_sym
|
76
80
|
end
|
77
81
|
|
82
|
+
# Returns the name of the controller in path form.
|
83
|
+
#
|
84
|
+
def self.controller_name
|
85
|
+
@controller_name ||= self.name.to_const_path
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns the name of the controller in path form.
|
89
|
+
#
|
90
|
+
def controller_name
|
91
|
+
self.class.controller_name
|
92
|
+
end
|
93
|
+
|
94
|
+
# Generates a URL based on the given name and passed
|
95
|
+
# options. Used with named routes and resources:
|
96
|
+
#
|
97
|
+
# url(:users) # => "/users"
|
98
|
+
# url(:admin_permissons) # => "/admin/permissions"
|
99
|
+
# url(:user, @user) # => "/users/1"
|
100
|
+
#
|
101
|
+
# Based on the identical method of Merb's controller.
|
102
|
+
#
|
103
|
+
def url(name, rparams={})
|
104
|
+
Halcyon::Application::Router.generate(name, rparams,
|
105
|
+
{ :controller => controller_name,
|
106
|
+
:action => method
|
107
|
+
}
|
108
|
+
)
|
109
|
+
end
|
110
|
+
|
111
|
+
#--
|
112
|
+
# Responders
|
113
|
+
#++
|
114
|
+
|
115
|
+
# Responds with the correct status and body specified.
|
116
|
+
#
|
117
|
+
# * +state+ a snake-case symbol of the status (ie, <tt>:not_found</tt>,
|
118
|
+
# <tt>:unprocessable_entity</tt>, or <tt>:forbidden</tt>)
|
119
|
+
# * +body+ the response body (if the default is insufficient)
|
120
|
+
#
|
121
|
+
# Examples:
|
122
|
+
#
|
123
|
+
# class Foos < Application
|
124
|
+
# def show
|
125
|
+
# if (foo = Foo[params[:id]])
|
126
|
+
# ok(foo)
|
127
|
+
# else
|
128
|
+
# status :not_found
|
129
|
+
# end
|
130
|
+
# end
|
131
|
+
# end
|
132
|
+
#
|
133
|
+
# The above example is the same as <tt>raise NotFound.new</tt>.
|
134
|
+
#
|
135
|
+
# If the state specified is not found, it will
|
136
|
+
# <tt>raise ServiceUnavailable.new</tt> (a <tt>503</tt> error). The error
|
137
|
+
# is then logged along with the backtrace.
|
138
|
+
#
|
139
|
+
def status(state, body = nil)
|
140
|
+
raise Halcyon::Exceptions.const_get(state.to_s.camel_case.to_sym).new(body)
|
141
|
+
rescue NameError => e
|
142
|
+
self.logger.error "Invalid status #{state.inspect} specified."
|
143
|
+
self.logger.error "Backtrace:\n" << e.backtrace.join("\n\t")
|
144
|
+
raise Halcyon::Exceptions::ServiceUnavailable.new
|
145
|
+
end
|
146
|
+
alias_method :error, :status
|
147
|
+
|
78
148
|
# Formats message into the standard success response hash, with a status of
|
79
149
|
# 200 (the standard success response).
|
80
150
|
# +body+ the body of the response
|
@@ -93,8 +163,9 @@ module Halcyon
|
|
93
163
|
# <tt>success</tt>
|
94
164
|
#
|
95
165
|
# Returns Hash:{:status=>200, :body=>body}
|
96
|
-
|
97
|
-
|
166
|
+
#
|
167
|
+
def ok(body='OK', headers = {})
|
168
|
+
{:status => 200, :body => body, :headers => headers}
|
98
169
|
end
|
99
170
|
alias_method :success, :ok
|
100
171
|
|
@@ -118,34 +189,93 @@ module Halcyon
|
|
118
189
|
# <tt>missing</tt>
|
119
190
|
#
|
120
191
|
# Returns Hash:{:status=>404, :body=>body}
|
121
|
-
|
122
|
-
|
192
|
+
#
|
193
|
+
def not_found(body='Not Found', headers = {})
|
194
|
+
{:status => 404, :body => body, :headers => headers}
|
123
195
|
end
|
124
196
|
alias_method :missing, :not_found
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
197
|
+
|
198
|
+
#--
|
199
|
+
# Filters
|
200
|
+
#++
|
201
|
+
|
202
|
+
class << self
|
203
|
+
|
204
|
+
# Creates +filters+ accessor method and initializes the +@filters+
|
205
|
+
# attribute with the necessary structure.
|
206
|
+
#
|
207
|
+
def filters
|
208
|
+
@filters ||= {:before => [], :after => []}
|
209
|
+
end
|
210
|
+
|
211
|
+
# Sets up filters for the method defined in the controllers.
|
212
|
+
#
|
213
|
+
# Examples
|
214
|
+
#
|
215
|
+
# class Foos < Application
|
216
|
+
# before :foo do
|
217
|
+
# #
|
218
|
+
# end
|
219
|
+
# after :blah, :only => [:foo]
|
220
|
+
# def foo
|
221
|
+
# # the block is called before the method is called
|
222
|
+
# # and the method is called after the method is called
|
223
|
+
# end
|
224
|
+
# private
|
225
|
+
# def blah
|
226
|
+
# #
|
227
|
+
# end
|
228
|
+
# end
|
229
|
+
#
|
230
|
+
# Options
|
231
|
+
# * +method_or_filter+ either the method to run before
|
232
|
+
#
|
233
|
+
def before method_or_filter, options={}, &block
|
234
|
+
_add_filter(:before, method_or_filter, options, block)
|
235
|
+
end
|
236
|
+
|
237
|
+
# See documentation for the +before+ method.
|
238
|
+
#
|
239
|
+
def after method_or_filter, options={}, &block
|
240
|
+
_add_filter(:after, method_or_filter, options, block)
|
241
|
+
end
|
242
|
+
|
243
|
+
# Used internally to save the filters, applied when called.
|
244
|
+
#
|
245
|
+
def _add_filter(where, method_or_filter, options, block)
|
246
|
+
self.filters[where] << [method_or_filter, options, block]
|
247
|
+
end
|
248
|
+
|
129
249
|
end
|
130
|
-
|
131
|
-
#
|
132
|
-
|
133
|
-
|
250
|
+
|
251
|
+
# Used internally.
|
252
|
+
#
|
253
|
+
# Applies the filters defined by the +before+ and +after+ class methods.
|
254
|
+
#
|
255
|
+
# +where+ specifies whether to apply <tt>:before</tt> or <tt>:after</tt>
|
256
|
+
# filters
|
257
|
+
# +action+ the routed action (for testing filter applicability)
|
258
|
+
#
|
259
|
+
def _run_filters(where, action)
|
260
|
+
self.class.filters[where].each do |(method_or_filter, options, block)|
|
261
|
+
if block
|
262
|
+
block.call(self) if _filter_condition_met?(method_or_filter, options, action)
|
263
|
+
else
|
264
|
+
send(method_or_filter) if _filter_condition_met?(method_or_filter, options, action)
|
265
|
+
end
|
266
|
+
end
|
134
267
|
end
|
135
|
-
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
{ :controller => controller_name,
|
147
|
-
:action => method
|
148
|
-
}
|
268
|
+
|
269
|
+
# Used internally.
|
270
|
+
#
|
271
|
+
# Tests whether a filter should be run for an action or not.
|
272
|
+
#
|
273
|
+
def _filter_condition_met?(method_or_filter, options, action)
|
274
|
+
(
|
275
|
+
options[:only] and options[:only].include?(action)) or
|
276
|
+
(options[:except] and !options[:except].include?(action)
|
277
|
+
) or (
|
278
|
+
method_or_filter == action
|
149
279
|
)
|
150
280
|
end
|
151
281
|
|