derailed-mole 1.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. data/History.txt +17 -0
  2. data/Manifest.txt +137 -0
  3. data/README.txt +216 -0
  4. data/Rakefile +46 -0
  5. data/bin/molify +64 -0
  6. data/config/database.yml +21 -0
  7. data/config/test_database.yml +69 -0
  8. data/lib/mole.rb +260 -0
  9. data/lib/mole/db/migrate.rb +90 -0
  10. data/lib/mole/e_mole.rb +75 -0
  11. data/lib/mole/e_mole_helper.rb +2 -0
  12. data/lib/mole/logger.rb +134 -0
  13. data/lib/mole/models/mole_feature.rb +58 -0
  14. data/lib/mole/models/mole_log.rb +31 -0
  15. data/lib/mole/module.rb +292 -0
  16. data/lib/mole/moler.rb +71 -0
  17. data/lib/mole/utils/frameworks.rb +53 -0
  18. data/lib/mole/version.rb +15 -0
  19. data/mole.gemspec +37 -0
  20. data/samples/merbapp/README +14 -0
  21. data/samples/merbapp/Rakefile +124 -0
  22. data/samples/merbapp/app/controllers/application.rb +3 -0
  23. data/samples/merbapp/app/controllers/exceptions.rb +13 -0
  24. data/samples/merbapp/app/controllers/moled.rb +25 -0
  25. data/samples/merbapp/app/helpers/global_helper.rb +5 -0
  26. data/samples/merbapp/app/mailers/views/layout/application.html.erb +1 -0
  27. data/samples/merbapp/app/mailers/views/layout/application.text.erb +1 -0
  28. data/samples/merbapp/app/parts/views/layout/application.html.erb +1 -0
  29. data/samples/merbapp/app/views/exceptions/internal_server_error.html.erb +216 -0
  30. data/samples/merbapp/app/views/exceptions/not_acceptable.html.erb +38 -0
  31. data/samples/merbapp/app/views/exceptions/not_found.html.erb +40 -0
  32. data/samples/merbapp/app/views/layout/application.html.erb +11 -0
  33. data/samples/merbapp/app/views/moled/index.html.erb +5 -0
  34. data/samples/merbapp/app/views/moled/result.html.erb +5 -0
  35. data/samples/merbapp/config/boot.rb +11 -0
  36. data/samples/merbapp/config/dependencies.rb +41 -0
  37. data/samples/merbapp/config/environments/development.rb +1 -0
  38. data/samples/merbapp/config/environments/production.rb +1 -0
  39. data/samples/merbapp/config/environments/test.rb +1 -0
  40. data/samples/merbapp/config/merb.yml +82 -0
  41. data/samples/merbapp/config/merb_init.rb +26 -0
  42. data/samples/merbapp/config/mole_config.rb +33 -0
  43. data/samples/merbapp/config/router.rb +38 -0
  44. data/samples/merbapp/config/upload.conf +0 -0
  45. data/samples/merbapp/public/images/merb.jpg +0 -0
  46. data/samples/merbapp/public/merb.fcgi +6 -0
  47. data/samples/merbapp/public/stylesheets/master.css +119 -0
  48. data/samples/merbapp/script/destroy +32 -0
  49. data/samples/merbapp/script/generate +32 -0
  50. data/samples/merbapp/script/stop_merb +13 -0
  51. data/samples/merbapp/spec/spec_helper.rb +15 -0
  52. data/samples/merbapp/test/test_helper.rb +14 -0
  53. data/samples/railsapp/README +14 -0
  54. data/samples/railsapp/Rakefile +10 -0
  55. data/samples/railsapp/app/controllers/application.rb +13 -0
  56. data/samples/railsapp/app/controllers/moled_controller.rb +24 -0
  57. data/samples/railsapp/app/helpers/application_helper.rb +3 -0
  58. data/samples/railsapp/app/views/moled/index.html.erb +5 -0
  59. data/samples/railsapp/app/views/moled/result.html.erb +5 -0
  60. data/samples/railsapp/config/boot.rb +109 -0
  61. data/samples/railsapp/config/database.yml +13 -0
  62. data/samples/railsapp/config/environment.rb +59 -0
  63. data/samples/railsapp/config/environments/development.rb +18 -0
  64. data/samples/railsapp/config/environments/production.rb +20 -0
  65. data/samples/railsapp/config/environments/test.rb +22 -0
  66. data/samples/railsapp/config/initializers/inflections.rb +10 -0
  67. data/samples/railsapp/config/initializers/mime_types.rb +5 -0
  68. data/samples/railsapp/config/initializers/mole.rb +10 -0
  69. data/samples/railsapp/config/moles/mole_config.rb +44 -0
  70. data/samples/railsapp/config/routes.rb +35 -0
  71. data/samples/railsapp/doc/README_FOR_APP +2 -0
  72. data/samples/railsapp/public/.htaccess +40 -0
  73. data/samples/railsapp/public/404.html +30 -0
  74. data/samples/railsapp/public/422.html +30 -0
  75. data/samples/railsapp/public/500.html +30 -0
  76. data/samples/railsapp/public/dispatch.cgi +10 -0
  77. data/samples/railsapp/public/dispatch.fcgi +24 -0
  78. data/samples/railsapp/public/dispatch.rb +10 -0
  79. data/samples/railsapp/public/favicon.ico +0 -0
  80. data/samples/railsapp/public/images/rails.png +0 -0
  81. data/samples/railsapp/public/javascripts/application.js +2 -0
  82. data/samples/railsapp/public/javascripts/controls.js +963 -0
  83. data/samples/railsapp/public/javascripts/dragdrop.js +972 -0
  84. data/samples/railsapp/public/javascripts/effects.js +1120 -0
  85. data/samples/railsapp/public/javascripts/prototype.js +4225 -0
  86. data/samples/railsapp/public/robots.txt +5 -0
  87. data/samples/railsapp/script/about +3 -0
  88. data/samples/railsapp/script/console +3 -0
  89. data/samples/railsapp/script/destroy +3 -0
  90. data/samples/railsapp/script/generate +3 -0
  91. data/samples/railsapp/script/performance/benchmarker +3 -0
  92. data/samples/railsapp/script/performance/profiler +3 -0
  93. data/samples/railsapp/script/performance/request +3 -0
  94. data/samples/railsapp/script/plugin +3 -0
  95. data/samples/railsapp/script/process/inspector +3 -0
  96. data/samples/railsapp/script/process/reaper +3 -0
  97. data/samples/railsapp/script/process/spawner +3 -0
  98. data/samples/railsapp/script/runner +3 -0
  99. data/samples/railsapp/script/server +3 -0
  100. data/samples/railsapp/test/test_helper.rb +38 -0
  101. data/samples/rubyapp/README +22 -0
  102. data/samples/rubyapp/bin/ruby_app +35 -0
  103. data/samples/rubyapp/config/mole_conf.rb +31 -0
  104. data/samples/rubyapp/lib/fred.rb +22 -0
  105. data/spec/config/auto_mole_config.rb +26 -0
  106. data/spec/config/mole_config.rb +0 -0
  107. data/spec/config/moles/fred_config.rb +0 -0
  108. data/spec/data/blee.rb +64 -0
  109. data/spec/db/migrate_spec.rb +19 -0
  110. data/spec/emole_spec.rb +43 -0
  111. data/spec/logger_spec.rb +56 -0
  112. data/spec/models/mole_feature_spec.rb +48 -0
  113. data/spec/models/mole_log_spec.rb +62 -0
  114. data/spec/module_spec.rb +229 -0
  115. data/spec/mole_spec.rb +135 -0
  116. data/spec/moler_spec.rb +77 -0
  117. data/spec/spec_helper.rb +76 -0
  118. data/spec/utils/framework_spec.rb +99 -0
  119. data/tasks/ann.rake +76 -0
  120. data/tasks/annotations.rake +22 -0
  121. data/tasks/doc.rake +48 -0
  122. data/tasks/gem.rake +110 -0
  123. data/tasks/manifest.rake +49 -0
  124. data/tasks/mole.rake +115 -0
  125. data/tasks/post_load.rake +26 -0
  126. data/tasks/rubyforge.rake +57 -0
  127. data/tasks/setup.rb +227 -0
  128. data/tasks/spec.rake +54 -0
  129. data/tasks/svn.rake +44 -0
  130. data/tasks/test.rake +38 -0
  131. data/templates/mole/e_mole/exception_alerts.rhtml +14 -0
  132. data/templates/mole/e_mole/feature_alerts.rhtml +11 -0
  133. data/templates/mole/e_mole/perf_alerts.rhtml +12 -0
  134. metadata +206 -0
data/lib/mole/moler.rb ADDED
@@ -0,0 +1,71 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Manages different ways to log the Mole interceptors. Currently there are two
3
+ # allowed modes ie persistent and transient
4
+ # Persistent mode will log the interception to the database for easy viewing
5
+ # and reporting.
6
+ # Transient mode will log the interaction to the mole logger.
7
+ # -----------------------------------------------------------------------------
8
+ module Mole
9
+ class Moler
10
+ class << self
11
+ # log an unchecked exception. Moler will look at the MOle
12
+ # configuration to see if this event should be persisted to the db or
13
+ # sent out to the logger.
14
+ def check_it( context, user_id, args )
15
+ return unless ::Mole.moleable?
16
+ # If exception is given record the first couple of frames
17
+ if args[:boom]
18
+ args[:trace] = dump_stack( args[:boom] )
19
+ args[:boom] = truncate( args[:boom].to_s )
20
+ end
21
+ if ::Mole.persistent?
22
+ MoleLog.log_it( context, MoleFeature::find_exception_feature( ::Mole.application ), user_id, args )
23
+ else
24
+ ::Mole.logger.log_it( context, "Exception", user_id, args )
25
+ end
26
+ # Send out email notification if requested
27
+ Mole::EMole.deliver_exception_alerts( context, user_id, args ) if args[:email] and args[:email] == true
28
+ end
29
+
30
+ # log performance occurence.
31
+ def perf_it( context, user_id, args )
32
+ return unless ::Mole.moleable?
33
+ if ::Mole.persistent?
34
+ MoleLog.log_it( context, MoleFeature::find_performance_feature( ::Mole.application ), user_id, args )
35
+ else
36
+ ::Mole.logger.log_it( context, "Performance", user_id, args )
37
+ end
38
+ # Send out email notification if requested
39
+ Mole::EMole.deliver_perf_alerts( context, user_id, args ) if args[:email] and args[:email] == true
40
+ end
41
+
42
+ # log a mole feature occurence.
43
+ def mole_it(context, feature, user_id, args)
44
+ return unless ::Mole.moleable?
45
+ if ::Mole.persistent?
46
+ MoleLog.log_it( context, MoleFeature::find_or_create_feature( feature, ::Mole.application, context.class.name ), user_id, args )
47
+ else
48
+ ::Mole.logger.log_it( context, feature, user_id, args )
49
+ end
50
+ # Send out email notification if requested
51
+ if args[:email] and args[:email] == true
52
+ args[:feature] = feature
53
+ Mole::EMole.deliver_feature_alerts( context, user_id, args )
54
+ end
55
+ end
56
+
57
+ # Truncate
58
+ def truncate(text, length = 200, truncate_string = "...")
59
+ return "" if text.nil?
60
+ l = length - truncate_string.chars.length
61
+ text.chars.length > length ? (text.chars[0...l] + truncate_string).to_s : text
62
+ end
63
+
64
+ # dumps partial stack
65
+ def dump_stack( boom )
66
+ return truncate( boom.backtrace[0] ) if boom.backtrace.size == 1
67
+ buff = boom.backtrace[0...3].join( "-" )
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,53 @@
1
+ # -----------------------------------------------------------------------------
2
+ # Convenience for extracting actions out controller classes
3
+ # Currently supported frameworks : Rails and Merb, more in the future...
4
+ # -----------------------------------------------------------------------------
5
+ module Mole
6
+ module Utils
7
+ class Frameworks
8
+ class << self
9
+
10
+ # compiles request parameters in a flat list.
11
+ def flatten_params( context )
12
+ return nil unless context.respond_to? :params
13
+ context.params.keys.sort{ |a,b| a.to_s <=> b.to_s }.collect{ |k| "#{k} => #{context.params[k]}" }.join( ", ")
14
+ end
15
+
16
+ # find moleable features for a given class
17
+ def features_for( controller_class )
18
+ # Try rails first
19
+ return rails_actions( controller_class ) rescue nil
20
+ # Try merb
21
+ return merb_actions( controller_class ) rescue nil
22
+ # Otherwise returns instance methods
23
+ moleable_features( controller_class )
24
+ end
25
+
26
+ # Find moleable features on a given class ie non moled instance methods
27
+ def moleable_features( clazz )
28
+ features = clazz.public_instance_methods( false )
29
+ features.select { |f| f unless f.index( /_(with|without)_mole/) }
30
+ end
31
+
32
+ # retrieves the collection of callable actions from a Merb controller.
33
+ def merb_actions( controller_class )
34
+ begin
35
+ actions = []
36
+ controller_class.send( :callable_actions ).keys.each { |action| actions << action }
37
+ rescue
38
+ raise "Invalid Merb Controller class `#{controller_class}"
39
+ end
40
+ end
41
+
42
+ # retrieves the collection of callable actions from a Rails controller
43
+ def rails_actions( controller_class )
44
+ begin
45
+ controller_class.send( :action_methods )
46
+ rescue
47
+ raise "Invalid Rails Controller class `#{controller_class}"
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,15 @@
1
+ module Mole
2
+ module Version
3
+ MAJOR = 1
4
+ MINOR = 0
5
+ TINY = 10
6
+
7
+ # Returns the version string for the library.
8
+ #
9
+ def self.version
10
+ [ MAJOR, MINOR, TINY].join( "." )
11
+ end
12
+ end
13
+ end
14
+
15
+
data/mole.gemspec ADDED
@@ -0,0 +1,37 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{mole}
3
+ s.version = "1.0.10"
4
+
5
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
6
+ s.authors = ["Fernand Galiana"]
7
+ s.date = %q{2008-08-31}
8
+ s.default_executable = %q{molify}
9
+ s.description = %q{A flexible way to track user's interactions within your ruby web applications}
10
+ s.email = %q{fernand@liquidrail.com}
11
+ s.executables = ["molify"]
12
+ s.extra_rdoc_files = ["History.txt", "README.txt", "bin/molify", "samples/railsapp/public/robots.txt"]
13
+ s.files = ["History.txt", "Manifest.txt", "README.txt", "Rakefile", "bin/molify", "config/database.yml", "config/test_database.yml", "lib/mole.rb", "lib/mole/db/migrate.rb", "lib/mole/e_mole.rb", "lib/mole/e_mole_helper.rb", "lib/mole/logger.rb", "lib/mole/models/mole_feature.rb", "lib/mole/models/mole_log.rb", "lib/mole/module.rb", "lib/mole/moler.rb", "lib/mole/utils/frameworks.rb", "lib/mole/version.rb", "mole.gemspec", "samples/merbapp/README", "samples/merbapp/Rakefile", "samples/merbapp/app/controllers/application.rb", "samples/merbapp/app/controllers/exceptions.rb", "samples/merbapp/app/controllers/moled.rb", "samples/merbapp/app/helpers/global_helper.rb", "samples/merbapp/app/mailers/views/layout/application.html.erb", "samples/merbapp/app/mailers/views/layout/application.text.erb", "samples/merbapp/app/parts/views/layout/application.html.erb", "samples/merbapp/app/views/exceptions/internal_server_error.html.erb", "samples/merbapp/app/views/exceptions/not_acceptable.html.erb", "samples/merbapp/app/views/exceptions/not_found.html.erb", "samples/merbapp/app/views/layout/application.html.erb", "samples/merbapp/app/views/moled/index.html.erb", "samples/merbapp/app/views/moled/result.html.erb", "samples/merbapp/config/boot.rb", "samples/merbapp/config/dependencies.rb", "samples/merbapp/config/environments/development.rb", "samples/merbapp/config/environments/production.rb", "samples/merbapp/config/environments/test.rb", "samples/merbapp/config/merb.yml", "samples/merbapp/config/merb_init.rb", "samples/merbapp/config/mole_config.rb", "samples/merbapp/config/router.rb", "samples/merbapp/config/upload.conf", "samples/merbapp/public/images/merb.jpg", "samples/merbapp/public/merb.fcgi", "samples/merbapp/public/stylesheets/master.css", "samples/merbapp/script/destroy", "samples/merbapp/script/generate", "samples/merbapp/script/stop_merb", "samples/merbapp/spec/spec_helper.rb", "samples/merbapp/test/test_helper.rb", "samples/railsapp/README", "samples/railsapp/Rakefile", "samples/railsapp/app/controllers/application.rb", "samples/railsapp/app/controllers/moled_controller.rb", "samples/railsapp/app/helpers/application_helper.rb", "samples/railsapp/app/views/moled/index.html.erb", "samples/railsapp/app/views/moled/result.html.erb", "samples/railsapp/config/boot.rb", "samples/railsapp/config/database.yml", "samples/railsapp/config/environment.rb", "samples/railsapp/config/environments/development.rb", "samples/railsapp/config/environments/production.rb", "samples/railsapp/config/environments/test.rb", "samples/railsapp/config/initializers/inflections.rb", "samples/railsapp/config/initializers/mime_types.rb", "samples/railsapp/config/initializers/mole.rb", "samples/railsapp/config/moles/mole_config.rb", "samples/railsapp/config/routes.rb", "samples/railsapp/doc/README_FOR_APP", "samples/railsapp/public/.htaccess", "samples/railsapp/public/404.html", "samples/railsapp/public/422.html", "samples/railsapp/public/500.html", "samples/railsapp/public/dispatch.cgi", "samples/railsapp/public/dispatch.fcgi", "samples/railsapp/public/dispatch.rb", "samples/railsapp/public/favicon.ico", "samples/railsapp/public/images/rails.png", "samples/railsapp/public/javascripts/application.js", "samples/railsapp/public/javascripts/controls.js", "samples/railsapp/public/javascripts/dragdrop.js", "samples/railsapp/public/javascripts/effects.js", "samples/railsapp/public/javascripts/prototype.js", "samples/railsapp/public/robots.txt", "samples/railsapp/script/about", "samples/railsapp/script/console", "samples/railsapp/script/destroy", "samples/railsapp/script/generate", "samples/railsapp/script/performance/benchmarker", "samples/railsapp/script/performance/profiler", "samples/railsapp/script/performance/request", "samples/railsapp/script/plugin", "samples/railsapp/script/process/inspector", "samples/railsapp/script/process/reaper", "samples/railsapp/script/process/spawner", "samples/railsapp/script/runner", "samples/railsapp/script/server", "samples/railsapp/test/test_helper.rb", "samples/rubyapp/README", "samples/rubyapp/bin/ruby_app", "samples/rubyapp/config/mole_conf.rb", "samples/rubyapp/lib/fred.rb", "spec/config/auto_mole_config.rb", "spec/config/mole_config.rb", "spec/config/moles/fred_config.rb", "spec/data/blee.rb", "spec/db/migrate_spec.rb", "spec/emole_spec.rb", "spec/logger_spec.rb", "spec/models/mole_feature_spec.rb", "spec/models/mole_log_spec.rb", "spec/module_spec.rb", "spec/mole_spec.rb", "spec/moler_spec.rb", "spec/spec_helper.rb", "spec/utils/framework_spec.rb", "tasks/ann.rake", "tasks/annotations.rake", "tasks/doc.rake", "tasks/gem.rake", "tasks/manifest.rake", "tasks/mole.rake", "tasks/post_load.rake", "tasks/rubyforge.rake", "tasks/setup.rb", "tasks/spec.rake", "tasks/svn.rake", "tasks/test.rake", "templates/mole/e_mole/exception_alerts.rhtml", "templates/mole/e_mole/feature_alerts.rhtml", "templates/mole/e_mole/perf_alerts.rhtml"]
14
+ s.has_rdoc = true
15
+ s.homepage = %q{http://mole.rubyforge.org}
16
+ s.rdoc_options = ["--main", "README.txt"]
17
+ s.require_paths = ["lib"]
18
+ s.rubyforge_project = %q{mole}
19
+ s.rubygems_version = %q{1.2.0}
20
+ s.summary = %q{A flexible way to track user's interactions within your ruby web applications}
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 2
25
+
26
+ if current_version >= 3 then
27
+ s.add_runtime_dependency(%q<logging>, ["= 0.9.0"])
28
+ s.add_runtime_dependency(%q<activerecord>, ["= 2.0.2"])
29
+ else
30
+ s.add_dependency(%q<logging>, ["= 0.9.0"])
31
+ s.add_dependency(%q<activerecord>, ["= 2.0.2"])
32
+ end
33
+ else
34
+ s.add_dependency(%q<logging>, ["= 0.9.0"])
35
+ s.add_dependency(%q<activerecord>, ["= 2.0.2"])
36
+ end
37
+ end
@@ -0,0 +1,14 @@
1
+ Sample MOled Merb App
2
+
3
+ NOTE: You must have merb installed
4
+
5
+
6
+ > cd samples/merbapp
7
+
8
+ Now launch merb
9
+
10
+ > merb
11
+
12
+ View the app by using the following url
13
+
14
+ http://localhost:4000
@@ -0,0 +1,124 @@
1
+ require 'rubygems'
2
+ Gem.clear_paths
3
+ Gem.path.unshift(File.join(File.dirname(__FILE__), "gems"))
4
+
5
+ require 'rake'
6
+ require 'rake/rdoctask'
7
+ require 'rake/testtask'
8
+ require 'spec/rake/spectask'
9
+ require 'fileutils'
10
+
11
+ require File.dirname(__FILE__)+'/config/boot.rb'
12
+ require Merb::framework_root+'/tasks'
13
+ include FileUtils
14
+
15
+ # Set these before any dependencies load
16
+ # otherwise the ORM may connect to the wrong env
17
+ Merb.root = File.dirname(__FILE__)
18
+ Merb.environment = ENV['MERB_ENV'] if ENV['MERB_ENV']
19
+
20
+ # Get Merb plugins and dependencies
21
+ require File.dirname(__FILE__)+'/config/dependencies.rb'
22
+ Merb::Plugins.rakefiles.each {|r| require r }
23
+
24
+ #desc "Packages up Merb."
25
+ #task :default => [:package]
26
+
27
+ desc "load merb_init.rb"
28
+ task :merb_init do
29
+ # deprecated - here for BC
30
+ Rake::Task['merb_env'].invoke
31
+ end
32
+
33
+ task :uninstall => [:clean] do
34
+ sh %{sudo gem uninstall #{NAME}}
35
+ end
36
+
37
+ desc 'Run unit tests'
38
+ Rake::TestTask.new('test_unit') do |t|
39
+ t.libs << 'test'
40
+ t.pattern = 'test/unit/*_test.rb'
41
+ t.verbose = true
42
+ end
43
+
44
+ desc 'Run functional tests'
45
+ Rake::TestTask.new('test_functional') do |t|
46
+ t.libs << 'test'
47
+ t.pattern = 'test/functional/*_test.rb'
48
+ t.verbose = true
49
+ end
50
+
51
+ desc 'Run all tests'
52
+ Rake::TestTask.new('test') do |t|
53
+ t.libs << 'test'
54
+ t.pattern = 'test/**/*_test.rb'
55
+ t.verbose = true
56
+ end
57
+
58
+ desc "Run all specs"
59
+ Spec::Rake::SpecTask.new('specs') do |t|
60
+ t.spec_opts = ["--format", "specdoc", "--colour"]
61
+ t.spec_files = Dir['spec/**/*_spec.rb'].sort
62
+ end
63
+
64
+ desc "Run all model specs"
65
+ Spec::Rake::SpecTask.new('model_specs') do |t|
66
+ t.spec_opts = ["--format", "specdoc", "--colour"]
67
+ t.spec_files = Dir['spec/models/**/*_spec.rb'].sort
68
+ end
69
+
70
+ desc "Run all controller specs"
71
+ Spec::Rake::SpecTask.new('controller_specs') do |t|
72
+ t.spec_opts = ["--format", "specdoc", "--colour"]
73
+ t.spec_files = Dir['spec/controllers/**/*_spec.rb'].sort
74
+ end
75
+
76
+ desc "Run a specific spec with TASK=xxxx"
77
+ Spec::Rake::SpecTask.new('spec') do |t|
78
+ t.spec_opts = ["--format", "specdoc", "--colour"]
79
+ t.libs = ['lib', 'server/lib' ]
80
+ t.spec_files = ["spec/merb/#{ENV['TASK']}_spec.rb"]
81
+ end
82
+
83
+ desc "Run all specs output html"
84
+ Spec::Rake::SpecTask.new('specs_html') do |t|
85
+ t.spec_opts = ["--format", "html"]
86
+ t.libs = ['lib', 'server/lib' ]
87
+ t.spec_files = Dir['spec/**/*_spec.rb'].sort
88
+ end
89
+
90
+ desc "RCov"
91
+ Spec::Rake::SpecTask.new('rcov') do |t|
92
+ t.spec_opts = ["--format", "specdoc", "--colour"]
93
+ t.spec_files = Dir['spec/**/*_spec.rb'].sort
94
+ t.libs = ['lib', 'server/lib' ]
95
+ t.rcov = true
96
+ end
97
+
98
+ desc 'Run all tests, specs and finish with rcov'
99
+ task :aok do
100
+ sh %{rake rcov}
101
+ sh %{rake spec}
102
+ end
103
+
104
+ unless Gem.cache.search("haml").empty?
105
+ namespace :haml do
106
+ desc "Compiles all sass files into CSS"
107
+ task :compile_sass do
108
+ gem 'haml'
109
+ require 'sass'
110
+ puts "*** Updating stylesheets"
111
+ Sass::Plugin.update_stylesheets
112
+ puts "*** Done"
113
+ end
114
+ end
115
+ end
116
+
117
+ ##############################################################################
118
+ # SVN
119
+ ##############################################################################
120
+
121
+ desc "Add new files to subversion"
122
+ task :svn_add do
123
+ system "svn status | grep '^\?' | sed -e 's/? *//' | sed -e 's/ /\ /g' | xargs svn add"
124
+ end
@@ -0,0 +1,3 @@
1
+ # all your other controllers should inherit from this one to share code.
2
+ class Application < Merb::Controller
3
+ end
@@ -0,0 +1,13 @@
1
+ class Exceptions < Application
2
+
3
+ # handle NotFound exceptions (404)
4
+ def not_found
5
+ render :format => :html
6
+ end
7
+
8
+ # handle NotAcceptable exceptions (406)
9
+ def not_acceptable
10
+ render :format => :html
11
+ end
12
+
13
+ end
@@ -0,0 +1,25 @@
1
+ # A plain old application controller that has been MOled...
2
+ class Moled < Application
3
+
4
+ def index
5
+ render
6
+ end
7
+
8
+ # A plain ol' feature
9
+ def my_action( id )
10
+ session[:user] = "Fernand"
11
+ @state = "Fred"
12
+ render :template => "moled/result"
13
+ end
14
+
15
+ # A slow action
16
+ def my_slow_action
17
+ sleep( 2 )
18
+ render :template => "moled/result"
19
+ end
20
+
21
+ # Hosed action
22
+ def my_hosed_action
23
+ raise "This will hose your app"
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ module Merb
2
+ module GlobalHelper
3
+ # helpers defined here available to all views.
4
+ end
5
+ end
@@ -0,0 +1 @@
1
+ <%= catch_content :layout %>
@@ -0,0 +1 @@
1
+ <%= catch_content :layout %>
@@ -0,0 +1 @@
1
+ <%= catch_content :layout %>
@@ -0,0 +1,216 @@
1
+ <html>
2
+ <head>
3
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8">
4
+ <title><%= @exception.name.humanize %></title>
5
+ <style type="text/css" media="screen">
6
+ body {
7
+ font-family:arial;
8
+ font-size:11px;
9
+ }
10
+ h1 {
11
+ font-size:48px;
12
+ letter-spacing:-4px;
13
+ margin:0;
14
+ line-height:36px;
15
+ color:#333;
16
+ }
17
+ h1 sup {
18
+ font-size: 0.5em;
19
+ }
20
+ h1 sup.error_500, h1 sup.error_400 {
21
+ color:#990E05;
22
+ }
23
+ h1 sup.error_100, h1 sup.error_200 {
24
+ color:#00BF10;
25
+ }
26
+ h1 sup.error_300 {
27
+ /* pretty sure you cant 'see' status 300
28
+ errors but if you could I think they
29
+ would be blue */
30
+ color:#1B2099;
31
+ }
32
+ h2 {
33
+ font-size:36px;
34
+ letter-spacing:-3px;
35
+ margin:0;
36
+ line-height:28px;
37
+ color:#444;
38
+ }
39
+ a, a:visited {
40
+ color:#00BF10;
41
+ }
42
+ .internalError {
43
+ width:800px;
44
+ margin:50px auto;
45
+ }
46
+ .header {
47
+ border-bottom:10px solid #333;
48
+ margin-bottom:1px;
49
+ background-image: url("data:image/gif;base64,R0lGODlhAwADAIAAAP///8zMzCH5BAAAAAAALAAAAAADAAMAAAIEBHIJBQA7");
50
+ padding:20px;
51
+ }
52
+ table.trace {
53
+ width:100%;
54
+ font-family:courier, monospace;
55
+ letter-spacing:-1px;
56
+ border-collapse: collapse;
57
+ border-spacing:0;
58
+ }
59
+ table.trace tr td{
60
+ padding:0;
61
+ height:26px;
62
+ font-size:13px;
63
+ vertical-align:middle;
64
+ }
65
+ table.trace tr.file{
66
+ border-top:2px solid #fff;
67
+ background-color:#F3F3F3;
68
+ }
69
+ table.trace tr.source {
70
+ background-color:#F8F8F8;
71
+ display:none;
72
+ }
73
+ table.trace .open tr.source {
74
+ display:table-row;
75
+ }
76
+ table.trace tr.file td.expand {
77
+ width:23px;
78
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAXCAIAAABvSEP3AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAdVJREFUeNqMVL+TwUAYxaRIOlEhlZHGDAUzzOQ61+AqXMV1lJSU7q/QRqm8KFUcJTNn5qJkaPyoKKVz7y4mF8na5Kt29tt9+/Z97/u81+vVQ4r9frdarS6Xi7ETDIZisRjxMGPfmk4niNPpZE+xLAugbPaZ53nzvtfMBe/3+/3dbuehBrAKhZdUKkVAWa9Xsiybv0CPZDJZLr/qa5/BwgwRjYqOKIvFYjQa/aNommZh0Ww2K5UqzwfoQOPxaLPZ3FAmk0+7lplMpt1u53J5OpBOR0eZEE9wHJfP5zud93g88QhluwWbjW+5VOmKBgKBer3eaDTDYeGBQF8+x7rqIYoiPgixWJazpA6HA+MSxRArkUgMh0M409g8Ho8+9wYxxCqVSq1W26EDHGM2m4HOHQrEc38f/Yn7cLmlIRhBENzcx8cVRZnPZ/YUep2BWkjTIfA+PKVpZAXR5QxsjiqCKvGEqqp443w+0dvy17swqD0HB3S73V5PpkNg1qBqt8kwGCjmPkinM0QJbIoEa7U6UG6ToVgs4V9G2g0ESoP5Aoi7KYX5oCgf8IKbkvn9/mr1LRQKESamzgJy0g0tSZIuB3nuGqRU9Vv9C4sKkUhEkp4soxvxI8AAhWrrtXa3X8EAAAAASUVORK5CYII=);
79
+ background-position:top left;
80
+ background-repeat:no-repeat;
81
+ }
82
+ table.trace .open tr.file td.expand {
83
+ width:19px;
84
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAB1CAIAAAAqdO2mAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAXZJREFUeNrslK1ywkAUhcMOBomEOiSdqLxEBJX0NaijOsjyHGGmCGyQQYaiiiw4gktkcOmZbpsuuzQ/M5XnqJ2d3S/n3nM3rTzPLUP7/Tt0+pLcGQwG3W53OLyHzPMtjYL7q9UqSRLrD4E1Gj1orCvKYuFHUWTVkOM44/HjDcp8/lL4r6NerzeZPMm1KFw0QkDn83m5fP2lHA4fNQvRtNvtjsfDd0WzmSfb2e/fdTqdOvdh/HLJZLOn0+d2HJ+KRGzbdl23EpFlmed5cp2maRzHQq1lvQ5KMi6EUZBGfup6E1pTfd+vrGW7jbQ2C9hTt9BpqNyIWaAwAy6xg2eBz5iRC/NomiZhGN5sqmnkauo0BUGgVQoBjQ80oCACgNQdZHfTYBkF2mxCtWWAqunWpahxIDUt3QYUxIFQpJHyIWpXjinabKbbwItMHT+NyjchrP8QKaSQQgoppJBCCimkkEIKKaSQQgoppJBCCimkkEIKKaSo+hRgAEFD17X08O2NAAAAAElFTkSuQmCC);
85
+ background-position:top left;
86
+ background-repeat:no-repeat;
87
+ }
88
+ table.trace tr.source td.collapse {
89
+ width:19px;
90
+ background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAB1CAIAAAAqdO2mAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAVxJREFUeNrs0zFygkAUBmBlUkgJHdABlQwVkVJKKUxBYWbkALTxMJwhltyDFkss03IF8pudIcwaDaDl/6pd2P327b7d+eHwMXs4lNkzggoVKlSoUKFChQoVKlSoUKFChQoVKlSoUKFChQqVEYqm6ft9+qiSJEkYho7jTlcw2fd9NOI4nq4gEdFwXXe1Cqco63VkWVbXRTqLhTpOwQRpF7quR1E0TgGhqvLKUFCyoQqG/rks3O6kZKW/eRFpevOCoGTXVTcMQ5EyxyDEkML1c5RzuZOICIyXqn7JBVez6282MWrx731HOv2qB8Hri2lamNk0DfpVVdV1Peodappmmua8bdvzuc7zfNprzrLMth1FnGh/X8MjCAIQv/cFz/+65PcDh7rbvYv2ZUfdj+PxsyzLgVl0hKwgTqeqKApx2LeOc7t98zyv/1FWOgvx9RPii23bmL9cetJ8Ed8CDAC6aFW8bCzFhwAAAABJRU5ErkJggg==);
91
+ background-position:bottom left;
92
+ background-repeat:no-repeat;
93
+ background-color:#6F706F;
94
+ }
95
+ table.trace tr td.path {
96
+ padding-left:10px;
97
+ }
98
+ table.trace tr td.code {
99
+ padding-left:35px;
100
+ white-space: pre;
101
+ line-height:9px;
102
+ padding-bottom:10px;
103
+ }
104
+ table.trace tr td.code em {
105
+ font-weight:bold;
106
+ color:#00BF10;
107
+ }
108
+ table.trace tr td.code a {
109
+ width: 20px;
110
+ float: left;
111
+ }
112
+ table.trace tr td.code .more {
113
+ color:#666;
114
+ }
115
+ table.trace tr td.line {
116
+ width:30px;
117
+ text-align:right;
118
+ padding-right:4px;
119
+ }
120
+ .footer {
121
+ margin-top:5px;
122
+ font-size:11px;
123
+ color:#444;
124
+ text-align:right;
125
+ }
126
+ </style>
127
+ </head>
128
+ <body>
129
+ <div class="internalError">
130
+
131
+ <div class="header">
132
+ <h1><%= @exception.name.humanize %> <sup class="error_<%= @exception.class::STATUS %>"><%= @exception.class::STATUS %></sup></h1>
133
+ <% if show_details = ::Merb::Config[:exception_details] -%>
134
+ <h2><%== @exception.message %></h2>
135
+ <% else -%>
136
+ <h2>Sorry about that...</h2>
137
+ <% end -%>
138
+ <h3>Parameters</h3>
139
+ <ul>
140
+ <% controller.params[:original_params].each do |param, value| %>
141
+ <li><strong><%= param %>:</strong> <%= value.inspect %></li>
142
+ <% end %>
143
+ <%= "<li>None</li>" if controller.params[:original_params].empty? %>
144
+ </ul>
145
+
146
+ <h3>Session</h3>
147
+ <ul>
148
+ <% controller.params[:original_session].each do |param, value| %>
149
+ <li><strong><%= param %>:</strong> <%= value.inspect %></li>
150
+ <% end %>
151
+ <%= "<li>None</li>" if controller.params[:original_session].empty? %>
152
+ </ul>
153
+
154
+ <h3>Cookies</h3>
155
+ <ul>
156
+ <% controller.params[:original_cookies].each do |param, value| %>
157
+ <li><strong><%= param %>:</strong> <%= value.inspect %></li>
158
+ <% end %>
159
+ <%= "<li>None</li>" if controller.params[:original_cookies].empty? %>
160
+ </ul>
161
+ </div>
162
+
163
+ <% if show_details %>
164
+ <table class="trace">
165
+ <% @exception.backtrace.each_with_index do |line, index| %>
166
+ <tbody class="close">
167
+ <tr class="file">
168
+ <td class="expand">
169
+ </td>
170
+ <td class="path">
171
+ <%= (line.match(/^([^:]+)/)[1] rescue 'unknown').sub(/\/((opt|usr)\/local\/lib\/(ruby\/)?(gems\/)?(1.8\/)?(gems\/)?|.+\/app\/)/, '') %>
172
+ <% unless line.match(/\.erb:/) %>
173
+ in "<strong><%= line.match(/:in `(.+)'$/)[1] rescue '?' %></strong>"
174
+ <% else %>
175
+ (<strong>ERB Template</strong>)
176
+ <% end %>
177
+ </td>
178
+ <td class="line">
179
+ <a href="txmt://open?url=file://<%=file = (line.match(/^([^:]+)/)[1] rescue 'unknown')%>&amp;line=<%= lineno = line.match(/:([0-9]+):/)[1] rescue '?' %>"><%=lineno%></a>&nbsp;
180
+ </td>
181
+ </tr>
182
+ <tr class="source">
183
+ <td class="collapse">
184
+ </td>
185
+ <td class="code" colspan="2"><% (__caller_lines__(file, lineno, 5) rescue []).each do |llineno, lcode, lcurrent| %>
186
+ <a href="txmt://open?url=file://<%=file%>&amp;line=<%=llineno%>"><%= llineno %></a><%='<em>' if llineno==lineno.to_i %><%= lcode.size > 90 ? CGI.escapeHTML(lcode[0..90])+'<span class="more">......</span>' : CGI.escapeHTML(lcode) %><%='</em>' if llineno==lineno.to_i %>
187
+ <% end %>
188
+
189
+ </td>
190
+ </tr>
191
+ </tbody>
192
+ <% end %>
193
+ </table>
194
+ <script type="text/javascript" charset="utf-8">
195
+ // swop the open & closed classes
196
+ els = document.getElementsByTagName('td');
197
+ for(i=0; i<els.length; i++){
198
+ if(els[i].className=='expand' || els[i].className=='collapse'){
199
+ els[i].onclick = function(e){
200
+ tbody = this.parentNode.parentNode;
201
+ if(tbody.className=='open'){
202
+ tbody.className='closed';
203
+ }else{
204
+ tbody.className='open';
205
+ }
206
+ }
207
+ }
208
+ }
209
+ </script>
210
+ <% end %>
211
+ <div class="footer">
212
+ lots of love, from <a href="#">merb</a>
213
+ </div>
214
+ </div>
215
+ </body>
216
+ </html>