public
Rubygem
Description: Merb Core: All you need. None you don't.
Homepage: http://www.merbivore.com
Clone URL: git://github.com/wycats/merb-core.git
Search Repo:
Michael S. Klishin (author)
Sun May 04 00:16:10 -0700 2008
commit  fffde1570f8f4c82d433e95350da79101396b1f6
tree    346fd4da20901a53be178130d992b8c5261cd3d9
parent  f35001ff89ff452ca1ac09cca3274cbd2912ffc4
merb-core / lib / merb-core.rb
100644 471 lines (424 sloc) 15.348 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
#---
# require 'merb' must happen after Merb::Config is instantiated
require 'rubygems'
require 'set'
require 'fileutils'
require 'socket'
 
$LOAD_PATH.unshift File.dirname(__FILE__) unless
  $LOAD_PATH.include?(File.dirname(__FILE__)) ||
  $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
 
module Merb
  module GlobalHelpers; end
  class << self
 
    # Startup Merb by setting up the Config and starting the server.
    # This is where Merb application environment and root path are set.
    #
    # ==== Parameters
    # argv<String, Hash>::
    # The config arguments to start Merb with. Defaults to +ARGV+.
    def start(argv=ARGV)
      if Hash === argv
        Merb::Config.setup(argv)
      else
        Merb::Config.parse_args(argv)
      end
      Merb.environment = Merb::Config[:environment]
      Merb.root = Merb::Config[:merb_root]
      case Merb::Config[:action]
      when :kill
        Merb::Server.kill(Merb::Config[:port], 1)
      when :kill_9
        Merb::Server.kill(Merb::Config[:port], 9)
      else
        Merb::Server.start(Merb::Config[:port], Merb::Config[:cluster])
      end
    end
 
    # Start the Merb environment, but only if it hasn't been loaded yet.
    #
    # ==== Parameters
    # argv<String, Hash>::
    # The config arguments to start Merb with. Defaults to +ARGV+.
    def start_environment(argv=ARGV)
      unless (@started ||= false)
        start(argv)
        @started = true
      end
    end
 
    # Restart the Merb environment explicitly.
    #
    # ==== Parameters
    # argv<String, Hash>::
    # The config arguments to restart Merb with. Defaults to +Merb::Config+.
    def restart_environment(argv={})
      @started = false
      start_environment(Merb::Config.to_hash.merge(argv))
    end
 
    attr_accessor :environment, :load_paths, :adapter
 
    alias :env :environment
 
    Merb.load_paths = Hash.new { [Merb.root] } unless Merb.load_paths.is_a?(Hash)
 
    # This is the core mechanism for setting up your application layout
    # merb-core won't set a default application layout, but merb-more will
    # use the app/:type layout:
    #
    # app/models for models
    # app/mailers for mailers (special type of controllers)
    # app/parts for parts, Merb components
    # app/views for templates
    # app/controllers for controller
    # lib for libraries
    #
    # ==== Notes
    # Autoloading for lib uses empty glob by default. If you
    # want to have your libraries under lib use autoload, add
    # the following to Merb init file:
    #
    # Merb.push_path(:lib, Merb.root / "lib", "**/*.rb") # glob set explicity.
    #
    # Then lib/magicwand/lib/magicwand.rb with MagicWand module will
    # be autoloaded when you first access that constant.
    #
    # ==== Examples
    # This method gives you a way to build up your own application
    # structure, for instance, to reflect the structure Rails
    # uses to simplify transition of legacy application, you can
    # set it up like this:
    #
    # Merb.push_path(:models, Merb.root / "app" / "models", "**/*.rb")
    # Merb.push_path(:mailers, Merb.root / "app" / "models", "**/*.rb")
    # Merb.push_path(:controllers, Merb.root / "app" / "controllers", "**/*.rb")
    # Merb.push_path(:views, Merb.root / "app" / "views", "**/*.rb")
    #
    # ==== Parameters
    # type<Symbol>:: The type of path being registered (i.e. :view)
    # path<String>:: The full path
    # file_glob<String>::
    # A glob that will be used to autoload files under the path. Defaults to
    # "**/*.rb".
    def push_path(type, path, file_glob = "**/*.rb")
      enforce!(type => Symbol)
      load_paths[type] = [path, file_glob]
    end
 
    # Removes given types of application components
    # from load path Merb uses for autoloading.
    #
    # ==== Parameters
    # *args<Array(Symbol)>::
    # components names, for instance, :views, :models
    #
    # ==== Examples
    # Using this combined with Merb::GlobalHelpers.push_path
    # you can make your Merb application use legacy Rails
    # application components.
    #
    # Merb.root = "path/to/legacy/app/root"
    # Merb.remove_paths(:mailers)
    # Merb.push_path(:mailers, Merb.root / "app" / "models", "**/*.rb")
    #
    # Will make Merb use app/models for mailers just like Ruby on Rails does.
    def remove_paths(*args)
      args.each {|arg| load_paths.delete(arg)}
    end
 
    # ==== Parameters
    # type<Symbol>:: The type of path to retrieve directory for, e.g. :view.
    #
    # ==== Returns
    # String:: The directory for the requested type.
    def dir_for(type) Merb.load_paths[type].first end
 
    # ==== Parameters
    # type<Symbol>:: The type of path to retrieve glob for, e.g. :view.
    #
    # ===== Returns
    # String:: The pattern with which to match files within the type directory.
    def glob_for(type) Merb.load_paths[type][1] end
 
    # ==== Returns
    # String:: The Merb root path.
    def root() @root || Merb::Config[:merb_root] || Dir.pwd end
 
    # ==== Parameters
    # value<String>:: Path to the root directory.
    def root=(value) @root = value end
 
    # ==== Parameters
    # *path::
    # The relative path (or list of path components) to a directory under the
    # root of the application.
    #
    # ==== Returns
    # String:: The full path including the root.
    #
    # ==== Examples
    # Merb.root = "/home/merb/app"
    # Merb.path("images") # => "/home/merb/app/images"
    # Merb.path("views", "admin") # => "/home/merb/app/views/admin"
    #---
    # @public
    def root_path(*path) File.join(root, *path) end
 
    # Logger settings
    attr_accessor :logger
 
    # ==== Returns
    # String::
    # The path to the log file. If this Merb instance is running as a daemon
    # this will return +STDOUT+.
    def log_file
      if Merb::Config[:log_file]
        Merb::Config[:log_file]
      elsif Merb.testing?
        log_path / "merb_test.log"
      elsif !(Merb::Config[:daemonize] || Merb::Config[:cluster])
        STDOUT
      else
        log_path / "merb.#{Merb::Config[:port]}.log"
      end
    end
 
    # ==== Returns
    # String:: Path to directory that contains the log file.
    def log_path
      case Merb::Config[:log_file]
      when String then File.dirname(Merb::Config[:log_file])
      else Merb.root_path("log")
      end
    end
 
    # ==== Returns
    # String:: The path of root directory of the Merb framework.
    def framework_root() @framework_root ||= File.dirname(__FILE__) end
 
    # ==== Returns
    # RegExp::
    # Regular expression against which deferred actions
    # are matched by Rack application handler.
    #
    # ==== Notes
    # Concatenates :deferred_actions configuration option
    # values.
    def deferred_actions
      @deferred ||= begin
        if Merb::Config[:deferred_actions].empty?
/^\0$/
        else
/#{Merb::Config[:deferred_actions].join("|")}/
        end
      end
    end
 
    # Allows flat apps by setting no default framework directories and yielding
    # a Merb::Router instance. This is optional since the router will
    # automatically configure the app with default routes.
    #
    # ==== Block parameters
    # r<Merb::Router::Behavior>::
    # The root behavior upon which new routes can be added.
    def flat!(framework = {})
      Merb::Config[:framework] = framework
 
      Merb::Router.prepare do |r|
        yield(r) if block_given?
        r.default_routes
      end
    end
 
    # Set up default variables under Merb
    attr_accessor :generator_scope, :klass_hashes
    Merb.generator_scope = [:merb_default, :merb, :rspec]
    Merb.klass_hashes = []
 
    attr_reader :registered_session_types
 
    # ==== Parameters
    # name<~to_s>:: Name of the session type to register.
    # file<String>:: The file that defines this session type.
    # description<String>:: An optional description of the session type.
    #
    # ==== Notes
    # Merb currently supports memory, cookie and memcache session
    # types.
    def register_session_type(name, file, description = nil)
      @registered_session_types ||= Dictionary.new
      @registered_session_types[name] = {
        :file => file,
        :description => (description || "Using #{name} sessions")
      }
    end
 
    attr_accessor :frozen
 
    # ==== Returns
    # Boolean:: True if Merb is running via script/frozen-merb or other freezer.
    #
    # ==== Notes
    # Freezing means bundling framework libraries with your application
    # making it independent from environment it runs in. This is a good
    # practice to freeze application framework and gems it uses and
    # very useful when application is run in some sort of sandbox,
    # for instance, shared hosting with preconfigured gems.
    def frozen?
      @frozen
    end
 
    # Used by script/frozen-merb and other freezers to mark Merb as frozen.
    # See Merb::GlobalHelpers.frozen? for more details on framework freezing.
    def frozen!
      @frozen = true
    end
 
    # Load configuration and assign logger.
    #
    # ==== Parameters
    # options<Hash>:: Options to pass on to the Merb config.
    #
    # ==== Options
    # :host<String>:: host to bind to,
    # default is 0.0.0.0.
    #
    # :port<Fixnum>:: port to run Merb application on,
    # default is 4000.
    #
    # :adapter<String>:: name of Rack adapter to use,
    # default is "runner"
    #
    # :rackup<String>:: name of Rack init file to use,
    # default is "rack.rb"
    #
    # :reload_classes<Boolean>:: whether Merb should reload
    # classes on each request,
    # default is true
    #
    # :environment<String>:: name of environment to use,
    # default is development
    #
    # :merb_root<String>:: Merb application root,
    # default is Dir.pwd
    #
    # :use_mutex<Boolean>:: turns action dispatch synchronization
    # on or off, default is on (true)
    #
    # :session_id_key<String>:: session identifier,
    # default is _session_id
    #
    # :log_delimiter<String>:: what Merb logger uses as delimiter
    # between message sections, default is " ~ "
    #
    # :log_auto_flush<Boolean>:: whether the log should automatically
    # flush after new messages are
    # added, defaults to true.
    #
    # :log_file<IO>:: IO for logger. Default is STDOUT.
    #
    # :log_level<Symbol>:: logger level, default is :warn
    #
    # :disabled_components<Array[Symbol]>::
    # array of disabled component names,
    # for instance, to disable json gem,
    # specify :json. Default is empty array.
    #
    # :deferred_actions<Array(Symbol, String)]>::
    # names of actions that should be deferred
    # no matter what controller they belong to.
    # Default is empty array.
    #
    # Some of these options come from command line on Merb
    # application start, some of them are set in Merb init file
    # or environment-specific.
    def load_config(options = {})
      Merb::Config.setup({ :log_file => STDOUT, :log_level => :warn, :log_auto_flush => true }.merge(options))
      Merb::BootLoader::Logger.run
    end
 
    # Load all basic dependencies (selected BootLoaders only).
    #
    # ==== Parameters
    # options<Hash>:: Options to pass on to the Merb config.
    def load_dependencies(options = {})
      load_config(options)
      Merb::BootLoader::BuildFramework.run
      Merb::BootLoader::Dependencies.run
      Merb::BootLoader::BeforeAppRuns.run
    end
 
    # Reload application and framework classes.
    # See Merb::BootLoader::ReloadClasses for details.
    def reload
      Merb::BootLoader::ReloadClasses.reload
    end
 
    # ==== Returns
    # Boolean:: True if Merb environment is testing for instance,
    # Merb is running with RSpec, Test::Unit of other testing facility.
    def testing?
      $TESTING || Merb::Config[:testing]
    end
 
    # Ask the question about which environment you're in.
    # ==== Parameters
    # env<Symbol, String>:: Name of the environment to query
    #
    # ==== Examples
    # Merb.env #=> production
    # Merb.env?(:production) #=> true
    # Merb.env?(:development) #=> false
    def env?(env)
      Merb.env == env.to_s
    end
 
    # If block was given configures using the block.
    #
    # ==== Parameters
    # &block:: Configuration parameter block, see example below.
    #
    # ==== Returns
    # Hash:: The current configuration.
    #
    # ==== Notes
    # See Merb::GlobalHelpers.load_config for configuration
    # options list.
    #
    # ==== Examples
    # Merb.config do
    # beer "good"
    # hashish :foo => "bar"
    # environment "development"
    # log_level "debug"
    # use_mutex false
    # session_store "cookie"
    # session_secret_key "0d05a226affa226623eb18700"
    # exception_details true
    # reload_classes true
    # reload_time 0.5
    # end
    def config(&block)
      Merb::Config.configure(&block) if block_given?
      Config
    end
 
    # Disables the given core components, like a Gem for example.
    #
    # ==== Parameters
    # *args:: One or more symbols of Merb internal components.
    def disable(*components)
      disabled_components.push *components
    end
 
    # ==== Parameters
    # Array:: All components that should be disabled.
    def disabled_components=(components)
      disabled_components.replace components
    end
 
    # ==== Returns
    # Array:: All components that have been disabled.
    def disabled_components
      Merb::Config[:disabled_components] ||= []
    end
 
    # ==== Returns
    # Boolean:: True if all components (or just one) are disabled.
    def disabled?(*components)
      components.all? { |c| disabled_components.include?(c) }
    end
 
    # ==== Returns
    # Array(String):: Paths Rakefiles are loaded from.
    #
    # ==== Notes
    # Recommended way to find out what paths Rakefiles
    # are loaded from.
    def rakefiles
      @rakefiles ||= ['merb-core/test/tasks/spectasks']
    end
 
    # ==== Parameters
    # *rakefiles:: Rakefile pathss to add to the list of Rakefiles.
    #
    # ==== Notes
    # Recommended way to add Rakefiles load path for plugins authors.
    def add_rakefiles(*rakefiles)
      @rakefiles ||= ['merb-core/test/tasks/spectasks']
      @rakefiles += rakefiles
    end
 
 
 
 
  end
end
 
require 'merb-core/autoload'
require 'merb-core/server'
require 'merb-core/gem_ext/erubis'
require 'merb-core/logger'
require 'merb-core/version'
require 'merb-core/controller/mime'
require 'merb-core/vendor/facets'
 
# Set the environment if it hasn't already been set.
Merb.environment ||= ENV['MERB_ENV'] || Merb::Config[:environment] || (Merb.testing? ? 'test' : 'development')