merb 0.3.4 → 0.3.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/README +206 -197
  2. data/Rakefile +12 -21
  3. data/bin/merb +1 -1
  4. data/examples/skeleton/Rakefile +6 -20
  5. data/examples/skeleton/dist/app/mailers/layout/application.erb +1 -0
  6. data/examples/skeleton/dist/conf/database.yml +23 -0
  7. data/examples/skeleton/dist/conf/environments/development.rb +1 -0
  8. data/examples/skeleton/dist/conf/environments/production.rb +1 -0
  9. data/examples/skeleton/dist/conf/environments/test.rb +1 -0
  10. data/examples/skeleton/dist/conf/merb.yml +32 -28
  11. data/examples/skeleton/dist/conf/merb_init.rb +16 -13
  12. data/examples/skeleton/dist/conf/router.rb +9 -9
  13. data/examples/skeleton/dist/schema/migrations/001_add_sessions_table.rb +2 -2
  14. data/lib/merb.rb +23 -18
  15. data/lib/merb/caching/fragment_cache.rb +3 -7
  16. data/lib/merb/caching/store/memcache.rb +20 -0
  17. data/lib/merb/core_ext/merb_array.rb +0 -0
  18. data/lib/merb/core_ext/merb_class.rb +44 -4
  19. data/lib/merb/core_ext/merb_enumerable.rb +43 -1
  20. data/lib/merb/core_ext/merb_hash.rb +200 -122
  21. data/lib/merb/core_ext/merb_kernel.rb +2 -0
  22. data/lib/merb/core_ext/merb_module.rb +41 -0
  23. data/lib/merb/core_ext/merb_numeric.rb +57 -5
  24. data/lib/merb/core_ext/merb_object.rb +172 -6
  25. data/lib/merb/generators/merb_app/merb_app.rb +15 -9
  26. data/lib/merb/merb_abstract_controller.rb +193 -0
  27. data/lib/merb/merb_constants.rb +26 -1
  28. data/lib/merb/merb_controller.rb +143 -234
  29. data/lib/merb/merb_dispatcher.rb +28 -20
  30. data/lib/merb/merb_drb_server.rb +2 -3
  31. data/lib/merb/merb_exceptions.rb +194 -49
  32. data/lib/merb/merb_handler.rb +34 -26
  33. data/lib/merb/merb_mail_controller.rb +200 -0
  34. data/lib/merb/merb_mailer.rb +33 -13
  35. data/lib/merb/merb_part_controller.rb +42 -0
  36. data/lib/merb/merb_plugins.rb +293 -0
  37. data/lib/merb/merb_request.rb +6 -4
  38. data/lib/merb/merb_router.rb +99 -65
  39. data/lib/merb/merb_server.rb +65 -21
  40. data/lib/merb/merb_upload_handler.rb +2 -1
  41. data/lib/merb/merb_view_context.rb +36 -15
  42. data/lib/merb/mixins/basic_authentication_mixin.rb +5 -5
  43. data/lib/merb/mixins/controller_mixin.rb +67 -28
  44. data/lib/merb/mixins/erubis_capture_mixin.rb +1 -8
  45. data/lib/merb/mixins/form_control_mixin.rb +280 -42
  46. data/lib/merb/mixins/render_mixin.rb +127 -45
  47. data/lib/merb/mixins/responder_mixin.rb +5 -7
  48. data/lib/merb/mixins/view_context_mixin.rb +260 -94
  49. data/lib/merb/session.rb +23 -0
  50. data/lib/merb/session/merb_ar_session.rb +28 -16
  51. data/lib/merb/session/merb_mem_cache_session.rb +108 -0
  52. data/lib/merb/session/merb_memory_session.rb +65 -20
  53. data/lib/merb/template/erubis.rb +22 -13
  54. data/lib/merb/template/haml.rb +5 -16
  55. data/lib/merb/template/markaby.rb +5 -3
  56. data/lib/merb/template/xml_builder.rb +17 -5
  57. data/lib/merb/test/merb_fake_request.rb +63 -0
  58. data/lib/merb/test/merb_multipart.rb +58 -0
  59. data/lib/tasks/db.rake +2 -0
  60. data/lib/tasks/merb.rake +20 -8
  61. metadata +24 -25
  62. data/examples/skeleton.tar +0 -0
@@ -13,7 +13,9 @@ module Merb
13
13
  @request.read
14
14
  end
15
15
 
16
- # returns true if the request is an ajax request.
16
+ # Returns true if the request is an Ajax request.
17
+ #
18
+ # Also aliased as the more memorable ajax? and xhr?.
17
19
  def xml_http_request?
18
20
  not /XMLHttpRequest/i.match(@env['HTTP_X_REQUESTED_WITH']).nil?
19
21
  end
@@ -24,15 +26,15 @@ module Merb
24
26
  def remote_ip
25
27
  return @env['HTTP_CLIENT_IP'] if @env.include?('HTTP_CLIENT_IP')
26
28
 
27
- if @env.include?(Mongrel::Const::HTTP_X_FORWARDED_FOR) then
28
- remote_ips = @env[Mongrel::Const::HTTP_X_FORWARDED_FOR].split(',').reject do |ip|
29
+ if @env.include?(Merb::Const::HTTP_X_FORWARDED_FOR) then
30
+ remote_ips = @env[Merb::Const::HTTP_X_FORWARDED_FOR].split(',').reject do |ip|
29
31
  ip =~ /^unknown$|^(127|10|172\.16|192\.168)\./i
30
32
  end
31
33
 
32
34
  return remote_ips.first.strip unless remote_ips.empty?
33
35
  end
34
36
 
35
- return @env[Mongrel::Const::REMOTE_ADDR]
37
+ return @env[Merb::Const::REMOTE_ADDR]
36
38
  end
37
39
 
38
40
  # returns either 'https://' or 'http://' depending on
@@ -6,7 +6,7 @@ module Merb
6
6
 
7
7
  class << self
8
8
 
9
- def prepare(&block)
9
+ def prepare
10
10
  @@matcher = RouteMatcher.new
11
11
  @@generator = RouteGenerator.new
12
12
 
@@ -31,8 +31,8 @@ module Merb
31
31
  @@matcher.route_request(path)
32
32
  end
33
33
 
34
- def generate(method, options = {})
35
- @@generator.generate(method, options)
34
+ def generate(method, *args)
35
+ @@generator.generate(method, *args)
36
36
  end
37
37
 
38
38
  def resources(res, opts={})
@@ -57,8 +57,8 @@ module Merb
57
57
  end
58
58
  end
59
59
 
60
- def default_routes
61
- @@matcher.default_routes
60
+ def default_routes(*a)
61
+ @@matcher.default_routes(*a)
62
62
  end
63
63
 
64
64
  def compiled_statement
@@ -80,32 +80,33 @@ module Merb
80
80
  end # class << self
81
81
 
82
82
  class RouteMatcher
83
-
83
+ attr_reader :routes, :compiled_statement, :compiled_regexen
84
+
84
85
  def initialize
85
86
  @routes = Array.new
87
+ # The final compiled lambda that gets used as the body of the route_request method.
86
88
  @compiled_statement = String.new
87
89
  @compiled_regexen = Array.new
88
90
  end
89
91
 
90
- # the final compiled lambda that gets used
91
- # as the body of the route_request method.
92
- def compiled_statement
93
- @compiled_statement
92
+ # Add a route to be compiled.
93
+ def add(*route)
94
+ opt = Hash === route.last ? route.pop : {}
95
+ if n = opt[:namespace]
96
+ path = "/#{n}#{route[0]}"
97
+ else
98
+ path = route[0]
99
+ end
100
+ @routes << [path, opt]
94
101
  end
95
102
 
96
- def compiled_regexen
97
- @compiled_regexen
98
- end
99
-
100
- # add a route to be compiled
101
- def add(*route)
102
- @routes << [route[0], (route[1] || {})]
103
+ def raw_add(*route)
104
+ @routes << [route[0], (route[1]||{})]
103
105
  end
104
106
 
105
- # build up a string that defines a lambda
106
- # that does a case statement on the PATH_INFO
107
- # against each of the compiled routes in turn.
108
- # first route that matches wins.
107
+ # Build up a string that defines a lambda that does a case statement on
108
+ # the PATH_INFO against each of the compiled routes in turn. First route
109
+ # that matches wins.
109
110
  def compile_router
110
111
  router_lambda = @routes.inject("lambda{|path| \n sections={}\n case path\n") { |m,r|
111
112
  m << compile(r)
@@ -114,11 +115,10 @@ module Merb
114
115
  meta_def(:route_request, &eval(router_lambda))
115
116
  end
116
117
 
117
- # compile each individual route into a when /.../
118
- # component of the case statement. Takes /:sections
119
- # of the route def that start with : and turns them
120
- # into placeholders for whatever urls match against
121
- # the route in question.
118
+ # Compile each individual route into a when /.../ component of the case
119
+ # statement. Takes /:sections of the route def that start with : and
120
+ # turns them into placeholders for whatever urls match against the route
121
+ # in question.
122
122
  def compile(route)
123
123
  raise ArgumentError unless String === route[0]
124
124
  code, count = '', 0
@@ -143,45 +143,48 @@ module Merb
143
143
  end
144
144
 
145
145
  def generate_resources_routes(res,opt)
146
- with_options :controller => res.to_s, :rest => true do |r|
147
- r.add "#{opt[:prefix]}/#{res}/:id[;/]edit", :allowed => {:get => 'edit'}
148
- r.add "#{opt[:prefix]}/#{res}/new[;/]:action", :allowed => {:get => 'new', :post => 'new', :put => 'new', :delete => 'new'}
149
- r.add "#{opt[:prefix]}/#{res}/new" , :allowed => {:get => 'new'}
146
+ with_options opt.merge(:controller => res.to_s, :rest => true) do |r|
147
+ r.raw_add "#{opt[:prefix]}/#{res}/:id[;/]edit", :allowed => {:get => 'edit'}
148
+ r.raw_add "#{opt[:prefix]}/#{res}/new[;/]:action", :allowed => {:get => 'new', :post => 'new', :put => 'new', :delete => 'new'}
149
+ r.raw_add "#{opt[:prefix]}/#{res}/new" , :allowed => {:get => 'new'}
150
150
  if mem = opt[:member]
151
151
  mem.keys.sort_by{|x| "#{x}"}.each {|action|
152
152
  allowed = mem[action].injecting({}) {|h, verb| h[verb] = "#{action}"}
153
- r.add "#{opt[:prefix]}/#{res}/:id[;/]+#{action}", :allowed => allowed
153
+ r.raw_add "#{opt[:prefix]}/#{res}/:id[;/]+#{action}", :allowed => allowed
154
154
  }
155
155
  end
156
156
  if coll = opt[:collection]
157
157
  coll.keys.sort_by{|x| "#{x}"}.each {|action|
158
158
  allowed = coll[action].injecting({}) {|h, verb| h[verb] = "#{action}"}
159
- r.add "#{opt[:prefix]}/#{res}[;/]#{action}", :allowed => allowed
159
+ r.raw_add "#{opt[:prefix]}/#{res}[;/]#{action}", :allowed => allowed
160
160
  }
161
161
  end
162
- r.add "#{opt[:prefix]}/#{res}/:id\\.:format", :allowed => {:get => 'show', :put => 'update', :delete => 'destroy'}
163
- r.add "#{opt[:prefix]}/#{res}\\.:format", :allowed => {:get => 'index', :post => 'create'}
164
- r.add "#{opt[:prefix]}/#{res}/:id", :allowed => {:get => 'show', :put => 'update', :delete => 'destroy'}
165
- r.add "#{opt[:prefix]}/#{res}/?", :allowed => {:get => 'index', :post => 'create'}
162
+ r.raw_add "#{opt[:prefix]}/#{res}/:id\\.:format", :allowed => {:get => 'show', :put => 'update', :delete => 'destroy'}
163
+ r.raw_add "#{opt[:prefix]}/#{res}\\.:format", :allowed => {:get => 'index', :post => 'create'}
164
+ r.raw_add "#{opt[:prefix]}/#{res}/:id", :allowed => {:get => 'show', :put => 'update', :delete => 'destroy'}
165
+ r.raw_add "#{opt[:prefix]}/#{res}/?", :allowed => {:get => 'index', :post => 'create'}
166
166
  end
167
167
  end
168
168
 
169
169
  def generate_singleton_routes(res,opt)
170
- with_options :controller => res.to_s, :rest => true do |r|
171
- r.add "#{opt[:prefix]}/#{res}[;/]edit", :allowed => {:get => 'edit'}
172
- r.add "#{opt[:prefix]}/#{res}\\.:format", :allowed => {:get => 'show'}
173
- r.add "#{opt[:prefix]}/#{res}/new" , :allowed => {:get => 'new'}
174
- r.add "#{opt[:prefix]}/#{res}/?", :allowed => {:get => 'show', :post => 'create', :put => 'update', :delete => 'destroy'}
170
+ with_options opt.merge(:controller => res.to_s, :rest => true ) do |r|
171
+ r.raw_add "#{opt[:prefix]}/#{res}[;/]edit", :allowed => {:get => 'edit'}
172
+ r.raw_add "#{opt[:prefix]}/#{res}\\.:format", :allowed => {:get => 'show'}
173
+ r.raw_add "#{opt[:prefix]}/#{res}/new" , :allowed => {:get => 'new'}
174
+ r.raw_add "#{opt[:prefix]}/#{res}/?", :allowed => {:get => 'show', :post => 'create', :put => 'update', :delete => 'destroy'}
175
175
  end
176
176
  end
177
177
 
178
- def default_routes
179
- add "/:controller/:action/:id\\.:format"
180
- add "/:controller/:action/:id"
181
- add "/:controller/:action\\.:format"
182
- add "/:controller/:action"
183
- add "/:controller\\.:format", :action => 'index'
184
- add "/:controller", :action => 'index'
178
+ def default_routes(opt={})
179
+ namespace = opt[:namespace] ? "/#{opt[:namespace]}" : ""
180
+ with_options opt do |r|
181
+ r.raw_add namespace + "/:controller/:action/:id\\.:format"
182
+ r.raw_add namespace + "/:controller/:action/:id"
183
+ r.raw_add namespace + "/:controller/:action\\.:format"
184
+ r.raw_add namespace + "/:controller/:action"
185
+ r.raw_add namespace + "/:controller\\.:format", :action => 'index'
186
+ r.raw_add namespace + "/:controller", :action => 'index'
187
+ end
185
188
  end
186
189
  end
187
190
 
@@ -194,14 +197,29 @@ module Merb
194
197
  end
195
198
 
196
199
  def add(name, path)
197
- name = name.intern unless Symbol === name
198
- @paths[name] = path
200
+ @paths[name.to_sym] = path
199
201
  end
200
-
201
- def generate(name, options = {})
202
+
203
+ def generate(name, *args)
204
+ options = Hash === args.last ? args.pop : {}
205
+ obj = args[0]
206
+ options.each do |key, value|
207
+ next unless value.respond_to?(:to_param)
208
+ unless key.to_s =~ /_?id$/
209
+ old_key = key
210
+ options[old_key] = value.to_param
211
+ key = "#{key}_id".intern
212
+ end
213
+ options[key] = value.to_param
214
+ end
215
+
202
216
  path = @paths[name].dup
203
217
  while path =~ Router::SECTION_REGEXP
204
- path.sub!(Router::SECTION_REGEXP, options[$~[1].intern].to_s)
218
+ if obj.respond_to?($1) && ! obj.nil?
219
+ path.sub!(Router::SECTION_REGEXP, obj.send($1).to_s)
220
+ else
221
+ path.sub!(Router::SECTION_REGEXP, options[$1.intern].to_s)
222
+ end
205
223
  end
206
224
  if f = options[:format]
207
225
  "#{path}.#{f}"
@@ -209,28 +227,44 @@ module Merb
209
227
  path
210
228
  end
211
229
  end
212
-
230
+
213
231
  def generate_singleton_routes(res,opt)
214
- add "edit_#{res}", "#{opt[:prefix]}/#{res}/edit"
215
- add "new_#{res}","#{opt[:prefix]}/#{res}/new"
216
- add res, "#{opt[:prefix]}/#{res}"
232
+ res = res.to_s
233
+ if opt[:namespace]
234
+ namespace = "#{opt[:namespace]}_"
235
+ name = "/#{opt[:namespace]}"
236
+ else
237
+ namespace = ''
238
+ name = ''
239
+ end
240
+ add namespace + "edit_#{res}", name + "#{opt[:prefix]}/#{res}/edit"
241
+ add namespace + "new_#{res}", name + "#{opt[:prefix]}/#{res}/new"
242
+ add namespace + res, name + "#{opt[:prefix]}/#{res}"
217
243
  end
218
244
 
219
245
  def generate_resources_routes(res,opt)
220
- res_singular = res.to_s.singularize
221
- add res, "#{opt[:prefix]}/#{res}"
222
- add res_singular, "#{opt[:prefix]}/#{res}/:id"
223
- add "new_#{res_singular}", "#{opt[:prefix]}/#{res}/new"
224
- add "custom_new_#{res_singular}", "#{opt[:prefix]}/#{res}/new/:action"
225
- add "edit_#{res_singular}", "#{opt[:prefix]}/#{res}/:id/edit"
246
+ res = res.to_s
247
+ res_singular = res.singularize
248
+ if opt[:namespace]
249
+ namespace = "#{opt[:namespace]}_"
250
+ name = "/#{opt[:namespace]}"
251
+ else
252
+ namespace = ''
253
+ name = ''
254
+ end
255
+ add namespace + res, name + "#{opt[:prefix]}/#{res}"
256
+ add namespace + res_singular, name + "#{opt[:prefix]}/#{res}/:id"
257
+ add namespace + "new_#{res_singular}", name + "#{opt[:prefix]}/#{res}/new"
258
+ add namespace + "custom_new_#{res_singular}", name + "#{opt[:prefix]}/#{res}/new/:action"
259
+ add namespace + "edit_#{res_singular}", name + "#{opt[:prefix]}/#{res}/:id/edit"
226
260
  if mem = opt[:member]
227
261
  mem.keys.sort_by{|x| "#{x}"}.each {|action|
228
- add "#{action}_#{res_singular}", "#{opt[:prefix]}/#{res}/:id/#{action}"
262
+ add namespace + "#{action}_#{res_singular}", name + "#{opt[:prefix]}/#{res}/:id/#{action}"
229
263
  }
230
264
  end
231
265
  if coll = opt[:collection]
232
266
  coll.keys.sort_by{|x| "#{x}"}.each {|action|
233
- add "#{action}_#{res_singular}", "#{opt[:prefix]}/#{res}/#{action}"
267
+ add namespace + "#{action}_#{res_singular}", name + "#{opt[:prefix]}/#{res}/#{action}"
234
268
  }
235
269
  end
236
270
  end
@@ -15,7 +15,9 @@ module Merb
15
15
  :allow_reloading => true,
16
16
  :merb_root => Dir.pwd,
17
17
  :cache_templates => false,
18
- :use_mutex => true
18
+ :use_mutex => true,
19
+ :session_id_cookie_only => true,
20
+ :query_string_whitelist => []
19
21
  }
20
22
  begin
21
23
  options = defaults.merge(YAML.load(Erubis::Eruby.new(IO.read("#{defaults[:merb_root]}/dist/conf/merb.yml")).result))
@@ -36,9 +38,9 @@ module Merb
36
38
 
37
39
  opts = OptionParser.new do |opts|
38
40
  opts.banner = "Usage: merb [fdcepghmisluMG] [argument]"
39
- opts.define_head "Merb Mongrel+ Erb. Lightweight replacement for ActionPack"
41
+ opts.define_head "Merb Mongrel+ Erb. Lightweight replacement for ActionPack."
40
42
  opts.separator '*'*80
41
- opts.separator 'If no flags are given, Merb starts in the foreground on port 4000'
43
+ opts.separator 'If no flags are given, Merb starts in the foreground on port 4000.'
42
44
  opts.separator '*'*80
43
45
 
44
46
  opts.on("-u", "--user USER", "This flag is for having merb run as a user other than the one currently logged in. Note: if you set this you must also provide a --group option for it to take effect.") do |config|
@@ -49,27 +51,27 @@ module Merb
49
51
  options[:group] = config
50
52
  end
51
53
 
52
- opts.on("-f", "--config-file FILENAME", "This flag is for adding extra config files for things like the upload progress module") do |config|
54
+ opts.on("-f", "--config-file FILENAME", "This flag is for adding extra config files for things like the upload progress module.") do |config|
53
55
  options[:config] = config
54
56
  end
55
57
 
56
- opts.on("-d", "--daemonize", "This will run a single merb in the background") do |config|
58
+ opts.on("-d", "--daemonize", "This will run a single merb in the background.") do |config|
57
59
  options[:daemonize] = true
58
60
  end
59
61
 
60
- opts.on("-c", "--cluster-nodes NUM_MERBS", "Number of merb daemons to run") do |nodes|
62
+ opts.on("-c", "--cluster-nodes NUM_MERBS", "Number of merb daemons to run.") do |nodes|
61
63
  options[:cluster] = nodes
62
64
  end
63
65
 
64
- opts.on("-p", "--port PORTNUM", "Port to run merb on, defaults to 4000") do |port|
66
+ opts.on("-p", "--port PORTNUM", "Port to run merb on, defaults to 4000.") do |port|
65
67
  options[:port] = port
66
68
  end
67
69
 
68
- opts.on("-h", "--host HOSTNAME", "Host to bind to(default is all IP's)") do |host|
70
+ opts.on("-h", "--host HOSTNAME", "Host to bind to (default is all IP's).") do |host|
69
71
  options[:host] = host
70
72
  end
71
73
 
72
- opts.on("-m", "--merb-root MERB_ROOT", "the path to the MERB_ROOT for the app you want to run") do |merb_root|
74
+ opts.on("-m", "--merb-root MERB_ROOT", "The path to the MERB_ROOT for the app you want to run (default is current working dir).") do |merb_root|
73
75
  options[:merb_root] = File.expand_path(merb_root)
74
76
  end
75
77
 
@@ -77,7 +79,7 @@ module Merb
77
79
  options[:console] = true
78
80
  end
79
81
 
80
- opts.on("-s", "--start-drb PORTNUM", "This is the port number to run the drb daemon on for sessions and uplod progress monitoring.") do |drb_port|
82
+ opts.on("-s", "--start-drb PORTNUM", "This is the port number to run the drb daemon on for sessions and upload progress monitoring.") do |drb_port|
81
83
  options[:start_drb] = true
82
84
  options[:only_drb] = true
83
85
  options[:drb_server_port] = drb_port
@@ -91,19 +93,23 @@ module Merb
91
93
  options[:environment] = env
92
94
  end
93
95
 
94
- opts.on("-r", "--script-runner ['RUBY CODE'| FULL_SCRIPT_PATH]", "Command-line option to run scripts and/or code in the merb app") do |stuff_to_run|
96
+ opts.on("-r", "--script-runner ['RUBY CODE'| FULL_SCRIPT_PATH]", "Command-line option to run scripts and/or code in the merb app.") do |stuff_to_run|
95
97
  options[:runner] = stuff_to_run
96
98
  end
97
99
 
98
- opts.on("-g", "--generate-app PATH", "Generate a fresh merb app at PATH") do |path|
100
+ opts.on("-g", "--generate-app PATH", "Generate a fresh merb app at PATH.") do |path|
99
101
  options[:generate] = path || Dir.pwd
100
102
  end
101
103
 
102
- opts.on("-k", "--kill PORT or all", "Kill one merb proceses by port number. use merb -k all to kill all merbs") do |ports|
104
+ opts.on("-P", "--plugin ACTION NAME", "Do ACTION with a plugin called NAME.") do |action|
105
+ options[:plugin] = [action, ARGV] || nil
106
+ end
107
+
108
+ opts.on("-k", "--kill PORT or all", "Kill one merb proceses by port number. use merb -k all to kill all merbs.") do |ports|
103
109
  options[:kill] = ports
104
110
  end
105
111
 
106
- opts.on("-M", "--merb-config FILENAME", "This flag is for explicitly declaring the merb app's config file") do |config|
112
+ opts.on("-M", "--merb-config FILENAME", "This flag is for explicitly declaring the merb app's config file.") do |config|
107
113
  options[:merb_config] = config
108
114
  end
109
115
 
@@ -131,9 +137,28 @@ module Merb
131
137
  # or if we add :merb_root: /path/to/merb/app in the merb.yml we can now only call it
132
138
  # like so: merb --merb-config /path/to/dist/conf/merb.yml
133
139
  if options[:merb_config]
140
+ # Check and see if an environment has been set through the CLI
141
+ # if so, save it in a temp. In this case, if merb.yml has an :environment:
142
+ # set... it will be overwritten by the CLI. [Rogelio J. Samour] 2007-06-07
143
+ if options[:environment]
144
+ temp_env = options[:environment]
145
+ end
134
146
  options = options.merge(YAML.load(Erubis::Eruby.new(IO.read("#{options[:merb_config]}")).result))
147
+ if temp_env
148
+ options[:environment] = temp_env
149
+ end
135
150
  end
136
151
 
152
+ if ENV['MERB_ENV']
153
+ # ENV['MERB_ENV'] has precedence over all
154
+ options[:environment] = ENV['MERB_ENV']
155
+ end
156
+
157
+ # Finally, if all else fails... set the environment to 'development'
158
+ if options[:environment].nil?
159
+ options[:environment] = 'development'
160
+ end
161
+
137
162
  @@merb_opts = options
138
163
  end
139
164
 
@@ -141,6 +166,7 @@ module Merb
141
166
  require 'merb'
142
167
  require @@merb_opts[:merb_root] / 'dist/conf/router.rb'
143
168
  require @@merb_opts[:merb_root] / 'dist/conf/merb_init.rb'
169
+
144
170
  end
145
171
 
146
172
  def run
@@ -180,8 +206,8 @@ module Merb
180
206
  end
181
207
 
182
208
  @@merb_opts[:dist_root] = @@merb_opts[:merb_root]+'/dist'
183
- $LOAD_PATH.unshift( File.join(@@merb_opts[:dist_root] , '/app/controllers') )
184
209
  $LOAD_PATH.unshift( File.join(@@merb_opts[:dist_root] , '/app/models') )
210
+ $LOAD_PATH.unshift( File.join(@@merb_opts[:dist_root] , '/app/controllers') )
185
211
  $LOAD_PATH.unshift( File.join(@@merb_opts[:dist_root] , '/lib') )
186
212
  if File.exist? File.join(@@merb_opts[:dist_root] , '/framework')
187
213
  $LOAD_PATH.unshift( File.join(@@merb_opts[:dist_root] , '/framework') )
@@ -193,17 +219,35 @@ module Merb
193
219
  exit!
194
220
  end
195
221
 
222
+ if @@merb_opts[:plugin]
223
+ require 'merb/merb_plugins'
224
+ ::Merb::PluginManager.action(@@merb_opts[:plugin].shift, @@merb_opts[:plugin][0].shift, @@merb_opts[:plugin])
225
+ exit!
226
+ end
227
+
196
228
  if @@merb_opts[:console]
197
229
  initialize_merb
198
- Object.class_eval do
199
- def show_routes
200
- Merb::Router.generator.paths.each {|p| puts p.inspect}
230
+ _merb = Class.new do
231
+ def self.show_routes(all_opts = false)
232
+ puts "== show_routes(all_opts = #{all_opts}) =="
233
+ puts "RouteMatcher:"
234
+ Merb::Router.matcher.routes.each {|route,opts| puts " #{route}" + (all_opts ? " " + opts.inspect : "") }
235
+ puts
236
+ puts "RouteGenerator:"
237
+ # Sort alphabetically by the url part of the route for easier reading.
238
+ Merb::Router.generator.paths.sort {|a,b| a.last <=> b.last }.each {|p| puts " " + p.inspect}
201
239
  nil
202
240
  end
203
- def url(path, o={})
204
- Merb::Router.generator.generate(path,o)
241
+
242
+ def self.url(path, *args)
243
+ Merb::Router.generate(path,*args)
205
244
  end
206
245
  end
246
+
247
+ Object.send(:define_method, :merb) {
248
+ _merb
249
+ }
250
+
207
251
  ARGV.clear # Avoid passing args to IRB
208
252
  require 'irb'
209
253
  require 'irb/completion'
@@ -306,7 +350,7 @@ module Merb
306
350
  listener do
307
351
  uri( "/", :handler => MerbUploadHandler.new(yconfig), :in_front => true) if @@merb_opts[:config]
308
352
  uri "/", :handler => MerbHandler.new(@@merb_opts[:dist_root]+'/public')
309
- uri "/favicon.ico", :handler => Mongrel::Error404Handler.new("")
353
+ uri "/favicon.ico", :handler => Mongrel::Error404Handler.new("")
310
354
  end
311
355
 
312
356
  trap("INT") { stop }