halcyon 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/Rakefile
CHANGED
@@ -92,6 +92,11 @@ namespace 'spec' do
|
|
92
92
|
task :verb do
|
93
93
|
sh "bacon -r~/lib/bacon/output -rlib/halcyon -rspec/spec_helper spec/**/* -o CSpecDox"
|
94
94
|
end
|
95
|
+
|
96
|
+
desc "run single rspec verbosely (specify SPEC)"
|
97
|
+
task :select do
|
98
|
+
sh "bacon -r~/lib/bacon/output -rlib/halcyon -rspec/spec_helper spec/**/#{ENV['SPEC']}_spec.rb -o CSpecDox"
|
99
|
+
end
|
95
100
|
end
|
96
101
|
|
97
102
|
desc "Do predistribution stuff"
|
data/lib/halcyon.rb
CHANGED
@@ -11,57 +11,75 @@ $:.unshift File.dirname(__FILE__)
|
|
11
11
|
# Halcyon.config #=> {:allow_from => :all, :logging => {...}, ...}
|
12
12
|
# Halcyon.paths #=> {:config => Halcyon.root/'config', ...}
|
13
13
|
# Halcyon.logger #=> #<Logger>
|
14
|
-
# Halcyon.version #=> "0.5.
|
14
|
+
# Halcyon.version #=> "0.5.1"
|
15
|
+
#
|
15
16
|
module Halcyon
|
16
17
|
|
17
|
-
VERSION = [0,5,
|
18
|
+
VERSION = [0,5,1] unless defined?(Halcyon::VERSION)
|
18
19
|
|
19
20
|
autoload :Application, 'halcyon/application'
|
20
21
|
autoload :Client, 'halcyon/client'
|
22
|
+
autoload :Config, 'halcyon/config'
|
21
23
|
autoload :Controller, 'halcyon/controller'
|
22
24
|
autoload :Exceptions, 'halcyon/exceptions'
|
23
25
|
autoload :Logging, 'halcyon/logging'
|
24
26
|
autoload :Runner, 'halcyon/runner'
|
25
27
|
|
28
|
+
include Config::Helpers
|
29
|
+
|
26
30
|
class << self
|
27
31
|
|
28
|
-
attr_accessor :app
|
29
32
|
attr_accessor :logger
|
30
|
-
|
31
|
-
attr_accessor :paths
|
33
|
+
attr_writer :config
|
32
34
|
|
33
35
|
def version
|
34
36
|
VERSION.join('.')
|
35
37
|
end
|
36
38
|
|
37
|
-
# The root
|
39
|
+
# The default <tt>root</tt> setting, overwritten by a configuration helper.
|
40
|
+
# This is so that the paths can be loaded when first booting the app.
|
41
|
+
# This won't be necessary for certain cases where the paths the root is
|
42
|
+
# manually configured, but for all other cases it can cause problems.
|
38
43
|
#
|
39
|
-
# Returns String:root_directory
|
40
44
|
def root
|
41
|
-
|
45
|
+
Dir.pwd
|
42
46
|
end
|
43
47
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
48
|
+
# Configuration accessor which creates a configuration object when
|
49
|
+
# necessary.
|
50
|
+
#
|
51
|
+
def config
|
52
|
+
@config ||= Halcyon::Config.new
|
53
|
+
end
|
54
|
+
|
55
|
+
# Tests for Windows platform (to compensate for numerous Windows-specific
|
56
|
+
# bugs and oddities.)
|
57
|
+
#
|
58
|
+
# Returns Boolean:is_windows
|
59
|
+
#
|
60
|
+
def windows?
|
61
|
+
RUBY_PLATFORM =~ /mswin/
|
62
|
+
end
|
63
|
+
|
64
|
+
# Tests for Linux platform.
|
65
|
+
#
|
66
|
+
# Returns Boolean:is_linux
|
67
|
+
#
|
68
|
+
def linux?
|
69
|
+
RUBY_PLATFORM =~ /linux/
|
54
70
|
end
|
55
|
-
alias_method :configurable_attr, :configurable
|
56
71
|
|
57
72
|
end
|
58
73
|
|
59
|
-
# Creates <tt>Halcyon.db</tt> to alias <tt>Halcyon.config[:db]</tt>.
|
60
|
-
# Also creates the complementary assignment method, <tt>Halcyon.db=</tt>
|
61
|
-
# that aliases <tt>Halcyon.config[:db]=</tt>.
|
62
|
-
configurable_attr :db
|
63
|
-
|
64
74
|
end
|
65
75
|
|
66
76
|
# Include the klass#logger and klass.logger accessor methods into Object.
|
67
77
|
Object.send(:include, Halcyon::Logging::Helpers)
|
78
|
+
|
79
|
+
# The server-interface framework.
|
80
|
+
#
|
81
|
+
module Rack
|
82
|
+
|
83
|
+
autoload :JSONP, 'rack/jsonp'
|
84
|
+
|
85
|
+
end
|
data/lib/halcyon/application.rb
CHANGED
@@ -7,21 +7,13 @@ module Halcyon
|
|
7
7
|
# Manages shutting down and starting up hooks, routing, dispatching, etc.
|
8
8
|
# Also restricts the requests to acceptable clients, defaulting to all.
|
9
9
|
#
|
10
|
-
class Application
|
11
|
-
include Exceptions
|
10
|
+
class Application
|
12
11
|
|
12
|
+
autoload :Hooks, 'halcyon/application/hooks'
|
13
13
|
autoload :Router, 'halcyon/application/router'
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
DEFAULT_OPTIONS = {
|
18
|
-
:root => Dir.pwd,
|
19
|
-
:logging => {
|
20
|
-
:type => 'Logger',
|
21
|
-
:level => 'info'
|
22
|
-
},
|
23
|
-
:allow_from => :all
|
24
|
-
}.to_mash
|
15
|
+
include Exceptions
|
16
|
+
include Hooks
|
25
17
|
|
26
18
|
# Initializes the app:
|
27
19
|
# * runs startup hooks
|
@@ -30,7 +22,7 @@ module Halcyon
|
|
30
22
|
def initialize
|
31
23
|
self.logger.info "Starting up..."
|
32
24
|
|
33
|
-
|
25
|
+
Halcyon.hooks[:startup].each {|hook| hook.call(Halcyon.config) }
|
34
26
|
|
35
27
|
# clean after ourselves and get prepared to start serving things
|
36
28
|
self.logger.debug "Starting GC."
|
@@ -40,7 +32,7 @@ module Halcyon
|
|
40
32
|
|
41
33
|
at_exit do
|
42
34
|
self.logger.info "Shutting down #{$$}."
|
43
|
-
|
35
|
+
Halcyon.hooks[:shutdown].each {|hook| hook.call(Halcyon.config) }
|
44
36
|
self.logger.info "Done."
|
45
37
|
end
|
46
38
|
end
|
@@ -92,11 +84,51 @@ module Halcyon
|
|
92
84
|
self.logger.error "#{e.message}\n\t" << e.backtrace.join("\n\t")
|
93
85
|
end
|
94
86
|
|
87
|
+
# This handles various sorts of response formats.
|
88
|
+
#
|
89
|
+
# The primary format is <tt>{:status => 200, :body => ...}</tt> which
|
90
|
+
# also supports a <tt>:headers</tt> entity (also a Hash).
|
91
|
+
#
|
92
|
+
# If this format is not followed, we assume they've just returned data so
|
93
|
+
# we package it up like normal and respond (for the user).
|
94
|
+
#
|
95
|
+
# The one exception to the previous rule is if the data is in the
|
96
|
+
# standard response structure [200, {}, 'OK'] or some such, we construct
|
97
|
+
# the reply accordingly.
|
98
|
+
#
|
99
|
+
response.status = 200 # we assume 200, but when specified get updated appropriately
|
100
|
+
result = case result
|
101
|
+
when Hash
|
102
|
+
if result[:status] and result[:body]
|
103
|
+
# {:status => 200, :body => 'OK'}
|
104
|
+
# no coercion necessary
|
105
|
+
result
|
106
|
+
else
|
107
|
+
# {*}
|
108
|
+
{:status => 200, :body => result}
|
109
|
+
end
|
110
|
+
when Array
|
111
|
+
if result[0].is_a?(Integer) and result[1].is_a?(Hash) and result[2]
|
112
|
+
# [200, {}, 'OK'] format followed
|
113
|
+
{:status => result[0], :headers => result[1], :body => result[2]}
|
114
|
+
else
|
115
|
+
# [*]
|
116
|
+
{:status => 200, :body => result}
|
117
|
+
end
|
118
|
+
else
|
119
|
+
# *
|
120
|
+
{:status => 200, :body => result}
|
121
|
+
end
|
122
|
+
# set response data
|
123
|
+
headers = result.delete(:headers) || {}
|
95
124
|
response.status = result[:status]
|
125
|
+
headers.each {|(header,val)| response[header] = val }
|
96
126
|
response.write result.to_json
|
97
127
|
|
98
128
|
timing[:finished] = Time.now
|
99
|
-
|
129
|
+
# the rescue is necessary if for some reason the timing is faster than
|
130
|
+
# system timing usec. this actually happens on Windows
|
131
|
+
timing[:total] = ((((timing[:finished] - timing[:started])*1e4).round.to_f/1e4) rescue 0.01)
|
100
132
|
timing[:per_sec] = (((1.0/(timing[:total]))*1e2).round.to_f/1e2)
|
101
133
|
|
102
134
|
self.logger.info "[#{response.status}] #{URI.parse(env['REQUEST_URI'] || env['PATH_INFO']).path} (#{timing[:total]}s;#{timing[:per_sec]}req/s)"
|
@@ -151,9 +183,34 @@ module Halcyon
|
|
151
183
|
# if no errors have occured up to this point, the route should be fully
|
152
184
|
# valid and all exceptions raised should be treated as
|
153
185
|
# <tt>500 Internal Server Error</tt>s, which is handled by <tt>call</tt>.
|
154
|
-
controller.
|
186
|
+
controller._dispatch(action)
|
155
187
|
end
|
156
188
|
|
189
|
+
# def apply_filters(where, controller, action)
|
190
|
+
# self.logger.debug "Applying #{where.to_s} filters to #{controller.class.to_s}##{action.to_s}"
|
191
|
+
# if controller.filters[:all].include?(action)
|
192
|
+
# controller.filters[:all][action].select {|filter| filter[:apply] == where}.each do |filter|
|
193
|
+
# if filter[:filter_or_block].is_a?(Proc)
|
194
|
+
# filter[:filter_or_block].call
|
195
|
+
# else
|
196
|
+
# controller.send(filter[:filter_or_block])
|
197
|
+
# end
|
198
|
+
# end
|
199
|
+
# end
|
200
|
+
# if controller.filters[:only].include?(action)
|
201
|
+
# controller.filters[:only][action].select {|filter| filter[:apply] == where && filter}.each do |filter|
|
202
|
+
# controller.send(filter[:filter_or_block])
|
203
|
+
# end
|
204
|
+
# end
|
205
|
+
# controller.filters[:except].each do |(filters_not_for_action, filters)|
|
206
|
+
# unless filters_not_for_action == action
|
207
|
+
# filters.each do |filter|
|
208
|
+
# controller.send(filter[:filter_or_block])
|
209
|
+
# end
|
210
|
+
# end
|
211
|
+
# end
|
212
|
+
# end
|
213
|
+
|
157
214
|
# Filters unacceptable requests depending on the configuration of the
|
158
215
|
# <tt>:allow_from</tt> option.
|
159
216
|
#
|
@@ -193,22 +250,8 @@ module Halcyon
|
|
193
250
|
request.params.merge(env['halcyon.route'])
|
194
251
|
end
|
195
252
|
|
196
|
-
# See the documentation for generated apps in <tt>config/initialze/hooks.rb</tt>
|
197
|
-
#
|
198
|
-
def hooks
|
199
|
-
self.class.hooks
|
200
|
-
end
|
201
|
-
|
202
253
|
class << self
|
203
254
|
|
204
|
-
attr_accessor :hooks
|
205
|
-
|
206
|
-
# See the documentation for generated apps in <tt>config/initialze/hooks.rb</tt>
|
207
|
-
#
|
208
|
-
def hooks
|
209
|
-
@hooks ||= {}
|
210
|
-
end
|
211
|
-
|
212
255
|
# Defines routes for the application.
|
213
256
|
#
|
214
257
|
# Refer to Halcyon::Application::Router for documentation and resources.
|
@@ -221,23 +264,69 @@ module Halcyon
|
|
221
264
|
end
|
222
265
|
end
|
223
266
|
|
224
|
-
|
225
|
-
#
|
226
|
-
|
227
|
-
# connections.
|
228
|
-
#
|
229
|
-
# Use initializers where possible.
|
230
|
-
#
|
231
|
-
def startup &hook
|
232
|
-
self.hooks[:startup] = hook
|
233
|
-
end
|
267
|
+
#--
|
268
|
+
# Boot Process
|
269
|
+
#++
|
234
270
|
|
235
|
-
#
|
236
|
-
|
237
|
-
|
271
|
+
# Used to keep track of whether the boot process has been run yet.
|
272
|
+
attr_accessor :booted
|
273
|
+
|
274
|
+
# Runs through the bootup process. This involves:
|
275
|
+
# * establishing configuration directives
|
276
|
+
# * loading required libraries
|
238
277
|
#
|
239
|
-
def
|
240
|
-
|
278
|
+
def boot(&block)
|
279
|
+
Halcyon.config ||= Halcyon::Config.new
|
280
|
+
|
281
|
+
# Set application name
|
282
|
+
Halcyon.app = Halcyon.config[:app] || Halcyon.root.split('/').last.camel_case
|
283
|
+
|
284
|
+
# Load configuration files (when available)
|
285
|
+
Dir.glob(%w(config app).map{|conf|Halcyon.paths[:config]/conf+'.{yml,yaml}'}).each do |config_file|
|
286
|
+
Halcyon.config.load_from(config_file) if File.exist?(config_file)
|
287
|
+
end
|
288
|
+
|
289
|
+
# Run configuration files (when available)
|
290
|
+
# These are unique in that they are Ruby files that we require so we
|
291
|
+
# can get rid of YAML config files and use Ruby configuration files.
|
292
|
+
Dir.glob(Halcyon.paths[:config]/'*.rb').each do |config_file|
|
293
|
+
require config_file
|
294
|
+
end
|
295
|
+
|
296
|
+
# Yield to the block to handle boot configuration (and other tasks).
|
297
|
+
Halcyon.config.use(&block) if block_given?
|
298
|
+
|
299
|
+
# Setup logger
|
300
|
+
if Halcyon.config[:logger]
|
301
|
+
Halcyon.config[:logging] = (Halcyon.config[:logging] || Halcyon::Config.defaults[:logging]).merge({
|
302
|
+
:type => Halcyon.config[:logger].class.to_s,
|
303
|
+
:logger => Halcyon.config[:logger]
|
304
|
+
})
|
305
|
+
end
|
306
|
+
Halcyon::Logging.set(Halcyon.config[:logging][:type])
|
307
|
+
Halcyon.logger = Halcyon::Logger.setup(Halcyon.config[:logging])
|
308
|
+
|
309
|
+
# Run initializers
|
310
|
+
Dir.glob(%w(requires hooks routes *).map{|init|Halcyon.paths[:init]/init+'.rb'}).each do |initializer|
|
311
|
+
self.logger.debug "Init: #{File.basename(initializer).chomp('.rb').camel_case}" if
|
312
|
+
require initializer.chomp('.rb')
|
313
|
+
end
|
314
|
+
|
315
|
+
# Setup autoloads for Controllers found in Halcyon.root/'app' (by default)
|
316
|
+
Dir.glob([Halcyon.paths[:controller]/'application.rb', Halcyon.paths[:controller]/'*.rb']).each do |controller|
|
317
|
+
self.logger.debug "Load: #{File.basename(controller).chomp('.rb').camel_case} Controller" if
|
318
|
+
require controller.chomp('.rb')
|
319
|
+
end
|
320
|
+
|
321
|
+
# Setup autoloads for Models found in Halcyon.root/'app'/'models' (by default)
|
322
|
+
Dir.glob(Halcyon.paths[:model]/'*.rb').each do |model|
|
323
|
+
self.logger.debug "Load: #{File.basename(model).chomp('.rb').camel_case} Model" if
|
324
|
+
require model.chomp('.rb')
|
325
|
+
end
|
326
|
+
|
327
|
+
# Set to loaded so additional calls to boot are ignored (unless
|
328
|
+
# forcefully loaded by ignoring this value).
|
329
|
+
self.booted = true
|
241
330
|
end
|
242
331
|
|
243
332
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Halcyon
|
2
|
+
class Application
|
3
|
+
|
4
|
+
# Helper that provides access to setting and running hooks.
|
5
|
+
#
|
6
|
+
module Hooks
|
7
|
+
|
8
|
+
# Extends the target with the class methods necessary.
|
9
|
+
def self.included(target)
|
10
|
+
target.extend(ClassMethods)
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
|
15
|
+
# Sets the startup hook to the proc.
|
16
|
+
#
|
17
|
+
# Use this to initialize application-wide resources, such as database
|
18
|
+
# connections.
|
19
|
+
#
|
20
|
+
# Use initializers where possible.
|
21
|
+
#
|
22
|
+
def startup &hook
|
23
|
+
Halcyon.hooks[:startup] << hook
|
24
|
+
end
|
25
|
+
|
26
|
+
# Sets the shutdown hook to the proc.
|
27
|
+
#
|
28
|
+
# Close any resources opened in the +startup+ hook.
|
29
|
+
#
|
30
|
+
def shutdown &hook
|
31
|
+
Halcyon.hooks[:shutdown] << hook
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,252 @@
|
|
1
|
+
module Halcyon
|
2
|
+
|
3
|
+
# Application configuration map.
|
4
|
+
#
|
5
|
+
class Config
|
6
|
+
|
7
|
+
attr_accessor :config
|
8
|
+
|
9
|
+
autoload :Helpers, 'halcyon/config/helpers'
|
10
|
+
autoload :Paths, 'halcyon/config/paths'
|
11
|
+
autoload :File, 'halcyon/config/file'
|
12
|
+
|
13
|
+
# Creates an empty configuration hash (Mash) and sets up the configuration
|
14
|
+
# to whatever the settings are provided, merging over the defaults.
|
15
|
+
#
|
16
|
+
# Examples:
|
17
|
+
#
|
18
|
+
# Halcyon::Config.new(:environment => :development)
|
19
|
+
#
|
20
|
+
# OR
|
21
|
+
#
|
22
|
+
# Halcyon::Config.new(:allow_from => :all)
|
23
|
+
#
|
24
|
+
# OR
|
25
|
+
#
|
26
|
+
# Halcyon::Config.new
|
27
|
+
#
|
28
|
+
# OR
|
29
|
+
#
|
30
|
+
# Halcyon::Config.new do |c|
|
31
|
+
# c[:foo] = true
|
32
|
+
# end
|
33
|
+
#
|
34
|
+
def initialize(config={}, &block)
|
35
|
+
env = config.delete(:environment)
|
36
|
+
self.config = Mash.new
|
37
|
+
self.setup(self.defaults(env).merge(config))
|
38
|
+
self.use(&block) if block_given?
|
39
|
+
end
|
40
|
+
|
41
|
+
# Sets the configuration up with the values given.
|
42
|
+
#
|
43
|
+
def configure(config={})
|
44
|
+
config.each do |(key, val)|
|
45
|
+
self.config[key] = val
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Sets up the configuration by storing the settings provided (via param or
|
50
|
+
# via block).
|
51
|
+
#
|
52
|
+
# Usage:
|
53
|
+
#
|
54
|
+
# Halcyon.config.setup do |c|
|
55
|
+
# c[:foo] = true
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# or
|
59
|
+
#
|
60
|
+
# Halcyon.config.setup(:foo => true)
|
61
|
+
#
|
62
|
+
def setup(config={})
|
63
|
+
if block_given?
|
64
|
+
yield(self.config.dup)
|
65
|
+
end
|
66
|
+
# merge new settings
|
67
|
+
self.configure(config)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Yields and returns the configuration.
|
71
|
+
#
|
72
|
+
# Examples:
|
73
|
+
#
|
74
|
+
# Halcyon.config.use do |c|
|
75
|
+
# c[:foo] = true
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
def use
|
79
|
+
if block_given?
|
80
|
+
yield self.config
|
81
|
+
end
|
82
|
+
self.config
|
83
|
+
end
|
84
|
+
|
85
|
+
# Allows retrieval of single key config values and setting single config
|
86
|
+
# values.
|
87
|
+
#
|
88
|
+
# Examples:
|
89
|
+
#
|
90
|
+
# Halcyon.config.app #=> 'AppName'
|
91
|
+
# Halcyon.config[:app] #=> 'AppName'
|
92
|
+
#
|
93
|
+
def method_missing(method, *args)
|
94
|
+
if method.to_s[-1,1] == '='
|
95
|
+
self.put(method.to_s.tr('=',''), *args)
|
96
|
+
else
|
97
|
+
self.get(method)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Get the configuration value associated with the key.
|
102
|
+
#
|
103
|
+
# Examples:
|
104
|
+
#
|
105
|
+
# Halcyon.config.get(:app) #=> 'AppName'
|
106
|
+
#
|
107
|
+
def get(key)
|
108
|
+
self.config[key]
|
109
|
+
end
|
110
|
+
|
111
|
+
# Put the configuration value associated with the key or setup with a hash.
|
112
|
+
#
|
113
|
+
# Examples:
|
114
|
+
#
|
115
|
+
# Halcyon.config.put(:app, 'AppName')
|
116
|
+
#
|
117
|
+
# OR
|
118
|
+
#
|
119
|
+
# Halcyon.config.put(:app => 'AppName')
|
120
|
+
#
|
121
|
+
def put(key_or_config_hash, value = nil)
|
122
|
+
if value.nil? and key_or_config_hash.is_a?(Hash)
|
123
|
+
self.configure(key_or_config_hash)
|
124
|
+
else
|
125
|
+
self.config[key_or_config_hash] = value
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Removes the configuration value from the hash.
|
130
|
+
#
|
131
|
+
# Examples:
|
132
|
+
#
|
133
|
+
# Halcyon.config.delete(:app) #=> 'AppName'
|
134
|
+
#
|
135
|
+
def delete(key)
|
136
|
+
self.config.delete(key)
|
137
|
+
end
|
138
|
+
|
139
|
+
# Alias for the <tt>get</tt> method.
|
140
|
+
#
|
141
|
+
# Examples:
|
142
|
+
#
|
143
|
+
# Halcyon.config[:foo] #=> true
|
144
|
+
#
|
145
|
+
def [](key)
|
146
|
+
self.get(key)
|
147
|
+
end
|
148
|
+
|
149
|
+
# Alias for the <tt>put</tt> method. (Restricted to the key/value pair.)
|
150
|
+
#
|
151
|
+
# Examples:
|
152
|
+
#
|
153
|
+
# Halcyon.config[:foo] = true
|
154
|
+
#
|
155
|
+
def []=(key, value)
|
156
|
+
self.put(key, value)
|
157
|
+
end
|
158
|
+
|
159
|
+
# Returns the configuration rendered as YAML.
|
160
|
+
#
|
161
|
+
def to_yaml
|
162
|
+
require 'yaml'
|
163
|
+
self.config.to_hash.to_yaml
|
164
|
+
end
|
165
|
+
|
166
|
+
# Returns the configuration as a hash.
|
167
|
+
#
|
168
|
+
def to_hash
|
169
|
+
self.config.to_hash
|
170
|
+
end
|
171
|
+
|
172
|
+
# Shortcut for Halcyon::Config.defaults.
|
173
|
+
#
|
174
|
+
def defaults(env = nil)
|
175
|
+
Halcyon::Config.defaults(env)
|
176
|
+
end
|
177
|
+
|
178
|
+
# Loads the contents of a configuration file found at <tt>path</tt> and
|
179
|
+
# merges it with the current configuration.
|
180
|
+
#
|
181
|
+
def load_from(path)
|
182
|
+
self.configure(Halcyon::Config::File.load(path))
|
183
|
+
self
|
184
|
+
end
|
185
|
+
|
186
|
+
def inspect
|
187
|
+
attrs = ""
|
188
|
+
self.config.keys.each {|key| attrs << " #{key}=#{self.config[key].inspect}"}
|
189
|
+
"#<Halcyon::Config#{attrs}>"
|
190
|
+
end
|
191
|
+
|
192
|
+
class << self
|
193
|
+
|
194
|
+
# Default configuration values.
|
195
|
+
#
|
196
|
+
# Defaults to the configuration for <tt>:development</tt>.
|
197
|
+
#
|
198
|
+
def defaults(env = nil)
|
199
|
+
base = {
|
200
|
+
:app => nil,
|
201
|
+
:root => Dir.pwd,
|
202
|
+
:environment => :development,
|
203
|
+
:allow_from => 'all',
|
204
|
+
:logging => {
|
205
|
+
:type => 'Logger',
|
206
|
+
:level => 'debug'
|
207
|
+
},
|
208
|
+
:paths => Paths.new,
|
209
|
+
:hooks => Hash.new([])
|
210
|
+
}
|
211
|
+
case (env || :development)
|
212
|
+
when :development
|
213
|
+
base.merge({
|
214
|
+
:environment => :development
|
215
|
+
})
|
216
|
+
when :test
|
217
|
+
base.merge({
|
218
|
+
:app => 'Specs',
|
219
|
+
:environment => :test,
|
220
|
+
:logging => {
|
221
|
+
:type => 'Logger',
|
222
|
+
:level => 'warn',
|
223
|
+
:file => 'log/test.log'
|
224
|
+
}
|
225
|
+
})
|
226
|
+
when :console
|
227
|
+
base.merge({
|
228
|
+
:environment => :console
|
229
|
+
})
|
230
|
+
when :production
|
231
|
+
base.merge({
|
232
|
+
:environment => :production,
|
233
|
+
:logging => {
|
234
|
+
:type => 'Logger',
|
235
|
+
:level => 'warn',
|
236
|
+
:file => 'log/production.log'
|
237
|
+
}
|
238
|
+
})
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
# Loads the contents of a configuration file found at <tt>path</tt>.
|
243
|
+
#
|
244
|
+
def load_from(path)
|
245
|
+
Halcyon::Config::File.load(path)
|
246
|
+
end
|
247
|
+
|
248
|
+
end
|
249
|
+
|
250
|
+
end
|
251
|
+
|
252
|
+
end
|