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
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
|