merb 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. data/README +21 -14
  2. data/Rakefile +157 -108
  3. data/SVN_REVISION +1 -0
  4. data/app_generators/merb/templates/Rakefile +20 -4
  5. data/app_generators/merb/templates/app/views/exceptions/internal_server_error.html.erb +1 -1
  6. data/app_generators/merb/templates/config/boot.rb +1 -1
  7. data/app_generators/merb/templates/config/dependencies.rb +3 -3
  8. data/app_generators/merb/templates/config/merb.yml +5 -0
  9. data/app_generators/merb/templates/config/merb_init.rb +3 -3
  10. data/app_generators/merb/templates/script/destroy +3 -0
  11. data/app_generators/merb/templates/script/generate +1 -1
  12. data/app_generators/merb/templates/spec/spec_helper.rb +2 -2
  13. data/app_generators/merb/templates/test/test_helper.rb +1 -1
  14. data/app_generators/merb_plugin/merb_plugin_generator.rb +4 -0
  15. data/bin/merb +1 -3
  16. data/lib/merb.rb +144 -76
  17. data/lib/merb/abstract_controller.rb +6 -5
  18. data/lib/merb/assets.rb +119 -0
  19. data/lib/merb/boot_loader.rb +217 -0
  20. data/lib/merb/caching.rb +1 -1
  21. data/lib/merb/caching/action_cache.rb +1 -1
  22. data/lib/merb/caching/fragment_cache.rb +1 -1
  23. data/lib/merb/caching/store/file_cache.rb +1 -1
  24. data/lib/merb/config.rb +290 -0
  25. data/lib/merb/controller.rb +5 -5
  26. data/lib/merb/core_ext/get_args.rb +1 -0
  27. data/lib/merb/core_ext/hash.rb +182 -169
  28. data/lib/merb/core_ext/kernel.rb +57 -26
  29. data/lib/merb/dispatcher.rb +6 -6
  30. data/lib/merb/drb_server.rb +1 -1
  31. data/lib/merb/generators/merb_generator_helpers.rb +7 -6
  32. data/lib/merb/logger.rb +1 -1
  33. data/lib/merb/mail_controller.rb +3 -4
  34. data/lib/merb/mailer.rb +2 -2
  35. data/lib/merb/mixins/basic_authentication.rb +2 -2
  36. data/lib/merb/mixins/controller.rb +1 -1
  37. data/lib/merb/mixins/general_controller.rb +13 -20
  38. data/lib/merb/mixins/inline_partial.rb +32 -0
  39. data/lib/merb/mixins/render.rb +3 -3
  40. data/lib/merb/mixins/responder.rb +1 -1
  41. data/lib/merb/mixins/view_context.rb +159 -33
  42. data/lib/merb/mongrel_handler.rb +9 -9
  43. data/lib/merb/plugins.rb +1 -1
  44. data/lib/merb/request.rb +25 -1
  45. data/lib/merb/router.rb +264 -226
  46. data/lib/merb/server.rb +66 -560
  47. data/lib/merb/session/cookie_store.rb +14 -13
  48. data/lib/merb/session/mem_cache_session.rb +20 -10
  49. data/lib/merb/session/memory_session.rb +21 -11
  50. data/lib/merb/template.rb +2 -2
  51. data/lib/merb/template/erubis.rb +3 -33
  52. data/lib/merb/template/haml.rb +8 -3
  53. data/lib/merb/test/fake_request.rb +8 -3
  54. data/lib/merb/test/helper.rb +66 -22
  55. data/lib/merb/test/rspec.rb +9 -155
  56. data/lib/merb/test/rspec_matchers/controller_matchers.rb +117 -0
  57. data/lib/merb/test/rspec_matchers/markup_matchers.rb +98 -0
  58. data/lib/merb/upload_handler.rb +2 -1
  59. data/lib/merb/version.rb +38 -3
  60. data/lib/merb/view_context.rb +1 -2
  61. data/lib/tasks/merb.rake +11 -11
  62. data/merb_generators/part_controller/USAGE +5 -0
  63. data/merb_generators/part_controller/part_controller_generator.rb +27 -0
  64. data/merb_generators/part_controller/templates/controller.rb +8 -0
  65. data/merb_generators/part_controller/templates/helper.rb +5 -0
  66. data/merb_generators/part_controller/templates/index.html.erb +3 -0
  67. data/rspec_generators/merb_controller_test/merb_controller_test_generator.rb +1 -1
  68. data/script/destroy +14 -0
  69. data/script/generate +14 -0
  70. data/spec/fixtures/controllers/dispatch_spec_controllers.rb +9 -1
  71. data/spec/fixtures/controllers/render_spec_controllers.rb +5 -5
  72. data/spec/fixtures/models/router_spec_models.rb +10 -0
  73. data/spec/merb/abstract_controller_spec.rb +2 -2
  74. data/spec/merb/assets_spec.rb +207 -0
  75. data/spec/merb/caching_spec.rb +2 -2
  76. data/spec/merb/controller_spec.rb +7 -2
  77. data/spec/merb/cookie_store_spec.rb +1 -1
  78. data/spec/merb/core_ext/class_spec.rb +97 -0
  79. data/spec/merb/core_ext/enumerable_spec.rb +27 -0
  80. data/spec/merb/core_ext/hash_spec.rb +251 -0
  81. data/spec/merb/core_ext/inflector_spec.rb +34 -0
  82. data/spec/merb/core_ext/kernel_spec.rb +25 -0
  83. data/spec/merb/core_ext/numeric_spec.rb +26 -0
  84. data/spec/merb/core_ext/object_spec.rb +47 -0
  85. data/spec/merb/core_ext/string_spec.rb +22 -0
  86. data/spec/merb/core_ext/symbol_spec.rb +7 -0
  87. data/spec/merb/dependency_spec.rb +22 -0
  88. data/spec/merb/dispatch_spec.rb +23 -12
  89. data/spec/merb/fake_request_spec.rb +8 -0
  90. data/spec/merb/generator_spec.rb +140 -21
  91. data/spec/merb/handler_spec.rb +5 -5
  92. data/spec/merb/mail_controller_spec.rb +3 -3
  93. data/spec/merb/render_spec.rb +1 -1
  94. data/spec/merb/responder_spec.rb +3 -3
  95. data/spec/merb/router_spec.rb +260 -191
  96. data/spec/merb/server_spec.rb +5 -5
  97. data/spec/merb/upload_handler_spec.rb +7 -0
  98. data/spec/merb/version_spec.rb +33 -0
  99. data/spec/merb/view_context_spec.rb +217 -59
  100. data/spec/spec_generator_helper.rb +15 -0
  101. data/spec/spec_helper.rb +5 -3
  102. data/spec/spec_helpers/url_shared_behaviour.rb +5 -7
  103. metadata +32 -7
  104. data/lib/merb/caching/store/memcache.rb +0 -20
  105. data/lib/merb/mixins/form_control.rb +0 -332
  106. data/lib/patch +0 -69
  107. data/spec/merb/core_ext_spec.rb +0 -464
  108. data/spec/merb/form_control_mixin_spec.rb +0 -431
@@ -0,0 +1,117 @@
1
+ module Merb
2
+ module Test
3
+ module ControllerMatchers
4
+
5
+ class BeRedirect
6
+ def matches?(target)
7
+ @target = target
8
+ target == 302
9
+ end
10
+ def failure_message
11
+ "expected to redirect"
12
+ end
13
+ def negative_failure_message
14
+ "expected not to redirect"
15
+ end
16
+ end
17
+
18
+ class Redirect
19
+ def matches?(target)
20
+ @target = target
21
+ BeRedirect.new.matches?(target.status)
22
+ end
23
+ def failure_message
24
+ "expected #{@target.inspect} to redirect"
25
+ end
26
+ def negative_failure_message
27
+ "expected #{@target.inspect} not to redirect"
28
+ end
29
+ end
30
+
31
+ class RedirectTo
32
+ def initialize(expected)
33
+ @expected = expected
34
+ end
35
+
36
+ def matches?(target)
37
+ @target = target.headers['Location']
38
+ @redirected = BeRedirect.new.matches?(target.status)
39
+ @target == @expected
40
+ end
41
+
42
+ def failure_message
43
+ msg = "expected a redirect to <#{@expected}>, but "
44
+ if @redirected
45
+ msg << "found one to <#{@target}>"
46
+ else
47
+ msg << "there was no redirect"
48
+ end
49
+ end
50
+
51
+ def negative_failure_message
52
+ "expected not to redirect to <#{@expected}>, but did anyway"
53
+ end
54
+ end
55
+
56
+ class BeSuccess
57
+
58
+ def matches?(target)
59
+ @target = target.status
60
+ (200..299).include?(@target)
61
+ end
62
+
63
+ def failure_message
64
+ "expected #{@target} to be successful but was #{@target.status}"
65
+ end
66
+
67
+ def negative_failure_message
68
+ "expected #{@target} not to be successful but it was"
69
+ end
70
+ end
71
+
72
+ class BeMissing
73
+ def matches?(target)
74
+ @target = target
75
+ (400..499).include?(@target.status)
76
+ end
77
+
78
+ def failurs_message
79
+ "expected #{@target} to be missing but was #{@target.status}"
80
+ end
81
+
82
+ def negative_failure_message
83
+ "expected #{@target} not to be missing but it was"
84
+ end
85
+ end
86
+
87
+
88
+ def be_redirect
89
+ BeRedirect.new
90
+ end
91
+
92
+ def redirect
93
+ Redirect.new
94
+ end
95
+
96
+ def redirect_to(expected)
97
+ RedirectTo.new(expected)
98
+ end
99
+
100
+ def be_success
101
+ BeSuccess.new
102
+ end
103
+
104
+ def be_successful
105
+ BeSuccess.new
106
+ end
107
+
108
+ def respond_successfully
109
+ BeSuccess.new
110
+ end
111
+
112
+ def be_missing
113
+ BeMissing.new
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,98 @@
1
+ module Merb
2
+ module Test
3
+ module MarkupMatchers
4
+ class HaveSelector
5
+ def initialize(expected)
6
+ @expected = expected
7
+ end
8
+
9
+ def matches?(stringlike)
10
+ @document = case stringlike
11
+ when Hpricot::Elem
12
+ stringlike
13
+ when StringIO
14
+ Hpricot.parse(stringlike.string)
15
+ else
16
+ Hpricot.parse(stringlike)
17
+ end
18
+ !@document.search(@expected).empty?
19
+ end
20
+
21
+ def failure_message
22
+ "expected following text to match selector #{@expected}:\n#{@document}"
23
+ end
24
+
25
+ def negative_failure_message
26
+ "expected following text to not match selector #{@expected}:\n#{@document}"
27
+ end
28
+ end
29
+
30
+ class MatchTag
31
+ def initialize(name, attrs)
32
+ @name, @attrs = name, attrs
33
+ @content = @attrs.delete(:content)
34
+ end
35
+
36
+ def matches?(target)
37
+ @errors = []
38
+ unless target.include?("<#{@name}")
39
+ @errors << "Expected a <#{@name}>, but was #{target}"
40
+ end
41
+ @attrs.each do |attr, val|
42
+ unless target.include?("#{attr}=\"#{val}\"")
43
+ @errors << "Expected #{attr}=\"#{val}\", but was #{target}"
44
+ end
45
+ end
46
+ if @content
47
+ unless target.include?(">#{@content}<")
48
+ @errors << "Expected #{target} to include #{@content}"
49
+ end
50
+ end
51
+ @errors.size == 0
52
+ end
53
+
54
+ def failure_message
55
+ @errors[0]
56
+ end
57
+
58
+ def negative_failure_message
59
+ "Expected not to match against <#{@name} #{@attrs.map{ |a,v| "#{a}=\"#{v}\"" }.join(" ")}> tag, but it matched"
60
+ end
61
+ end
62
+
63
+ class NotMatchTag
64
+ def initialize(attrs)
65
+ @attrs = attrs
66
+ end
67
+
68
+ def matches?(target)
69
+ @errors = []
70
+ @attrs.each do |attr, val|
71
+ if target.include?("#{attr}=\"#{val}\"")
72
+ @errors << "Should not include #{attr}=\"#{val}\", but was #{target}"
73
+ end
74
+ end
75
+ @errors.size == 0
76
+ end
77
+
78
+ def failure_message
79
+ @errors[0]
80
+ end
81
+ end
82
+
83
+ def match_tag(name, attrs={})
84
+ MatchTag.new(name, attrs)
85
+ end
86
+ def not_match_tag(attrs)
87
+ NotMatchTag.new(attrs)
88
+ end
89
+
90
+ def have_selector(expected)
91
+ HaveSelector.new(expected)
92
+ end
93
+ alias_method :match_selector, :have_selector
94
+
95
+
96
+ end
97
+ end
98
+ end
@@ -56,7 +56,8 @@ class MerbUploadHandler < Mongrel::HttpHandler
56
56
  def request_aborted(params)
57
57
  return unless upload_id = valid_upload?(params)
58
58
  Mongrel::Uploads.finish(upload_id)
59
- puts "request aborted!"
59
+ Merb.logger.info "#{self.class.name} - request aborted for " <<
60
+ "id: #{upload_id.inspect}, params: #{params.inspect}"
60
61
  end
61
62
 
62
63
  private
@@ -1,5 +1,38 @@
1
1
  module Merb
2
- VERSION='0.4.2' unless defined?(::Merb::VERSION)
2
+ VERSION = '0.5.0' unless defined?(::Merb::VERSION)
3
+
4
+ class << self
5
+ def svn_revision
6
+ rev = if File.directory?('.git')
7
+ `git log -1`[/git-svn-id.+@(\d+)/, 1]
8
+ elsif File.directory?('.svn')
9
+ `svn info`[/Revision: (\d+)/, 1]
10
+ end
11
+ rev = rev.to_i if rev
12
+ end
13
+
14
+ def svn_revision_filename
15
+ 'SVN_REVISION'
16
+ end
17
+
18
+ def svn_revision_from_file
19
+ begin
20
+ File.open svn_revision_file_path, 'w' do |f|
21
+ f.print svn_revision
22
+ end
23
+ # catch permissions error when packaged as gem
24
+ rescue Errno::EACCES
25
+ end
26
+
27
+ unless (rev = File.read(svn_revision_file_path).strip).empty?
28
+ rev.to_i
29
+ end
30
+ end
31
+
32
+ def svn_revision_file_path
33
+ File.expand_path File.join(File.dirname(__FILE__), '..', '..', svn_revision_filename)
34
+ end
35
+ end
3
36
 
4
37
  # Merb::RELEASE meanings:
5
38
  # 'svn' : unreleased
@@ -7,5 +40,7 @@ module Merb
7
40
  # nil : released
8
41
  # You should never check in to trunk with this changed. It should
9
42
  # stay 'svn'. Change it to nil in release tags.
10
- RELEASE='svn' unless defined?(::Merb::RELEASE)
11
- end
43
+ unless defined?(::Merb::RELEASE)
44
+ RELEASE = "svn#{" r#{svn_revision_from_file}" if svn_revision_from_file}"
45
+ end
46
+ end
@@ -33,7 +33,6 @@ module Merb
33
33
  # the context object passed to Erubis when evaluating the templates.
34
34
  class ViewContext
35
35
  include Merb::ViewContextMixin
36
- include Merb::FormControls
37
36
  include Merb::WebControllerMixin
38
37
 
39
38
  def initialize(controller)
@@ -45,7 +44,7 @@ module Merb
45
44
  begin
46
45
  self.class.class_eval(" include Merb::GlobalHelper; include Merb::#{@web_controller.class.name}Helper")
47
46
  rescue NameError
48
- MERB_LOGGER.debug("Missing Helper: Merb::#{@web_controller.class.name}Helper")
47
+ Merb.logger. debug("Missing Helper: Merb::#{@web_controller.class.name}Helper")
49
48
  end
50
49
  end
51
50
 
@@ -1,5 +1,5 @@
1
1
  def install_merb_script
2
- script_filepath = MERB_ROOT / 'script/merb'
2
+ script_filepath = Merb.root / 'script/merb'
3
3
  FileUtils.rm script_filepath if File.exist? script_filepath
4
4
  tmpl = "#!/usr/bin/env ruby\nrequire File.expand_path(File.dirname(__FILE__)+'/../framework/merb/server')\nMerb::Server.run\n"
5
5
  File.open(script_filepath, 'wb') {|f|
@@ -11,8 +11,8 @@ end
11
11
  namespace :merb do
12
12
  desc "freeze the merb framework into merb for portability"
13
13
  task :freeze do
14
- FileUtils.rm_rf MERB_ROOT / 'framework'
15
- FileUtils.cp_r MERB_FRAMEWORK_ROOT, (MERB_ROOT / 'framework')
14
+ FileUtils.rm_rf Merb.root / 'framework'
15
+ FileUtils.cp_r Merb::framework_root, (Merb.root / 'framework')
16
16
  install_merb_script
17
17
 
18
18
  puts " Freezing Merb Framework into framework"
@@ -20,17 +20,17 @@ namespace :merb do
20
20
  end
21
21
  desc "unfreeze this app from the framework and use system gem."
22
22
  task :unfreeze do
23
- FileUtils.rm_rf MERB_ROOT / 'framework'
24
- FileUtils.rm MERB_ROOT / 'script/merb'
23
+ FileUtils.rm_rf Merb.root / 'framework'
24
+ FileUtils.rm Merb.root / 'script/merb'
25
25
 
26
26
  puts " Removed: "
27
- puts " - #{MERB_ROOT / 'framework'} (recursive) "
28
- puts " - #{MERB_ROOT / 'script/merb'}"
27
+ puts " - #{Merb.root / 'framework'} (recursive) "
28
+ puts " - #{Merb.root / 'script/merb'}"
29
29
  end
30
30
 
31
31
  desc "freeze the merb framework from svn, use REVISION=# to freeze a specific revision"
32
32
  task :freeze_from_svn do
33
- install_path = MERB_ROOT / 'framework'
33
+ install_path = Merb.root / 'framework'
34
34
  revision = ENV['REVISION'] || 'HEAD'
35
35
  puts " Removing old framework" if File.exist? install_path
36
36
  FileUtils.rm_rf install_path
@@ -48,7 +48,7 @@ desc "Setup the Merb Environment by requiring merb and loading your merb_init.rb
48
48
  task :merb_env do
49
49
  require 'rubygems'
50
50
  require 'merb'
51
- Merb::Server.config[:environment] = ENV['MERB_ENV'] if ENV['MERB_ENV']
52
- MERB_ENV = Merb::Server.config[:environment].nil? ? 'development' : Merb::Server.config[:environment]
53
- load MERB_ROOT+'/config/merb_init.rb'
51
+ Merb::Config[:environment] = ENV['Merb.environment'] if ENV['Merb.environment']
52
+ Merb.environment = Merb::Config[:environment].nil? ? 'development' : Merb::Config[:environment]
53
+ load Merb.root+'/config/merb_init.rb'
54
54
  end
@@ -0,0 +1,5 @@
1
+ Description:
2
+ Generates a PartController
3
+
4
+ Usage:
5
+ script/generate part_controller name
@@ -0,0 +1,27 @@
1
+ require 'merb/generators/merb_generator_helpers'
2
+
3
+ class PartControllerGenerator < Merb::GeneratorHelpers::ControllerGeneratorBase
4
+
5
+ def initialize(*args)
6
+ runtime_options = args.last.is_a?(Hash) ? args.pop : {}
7
+ name, *actions = args.flatten
8
+ name += "_part"
9
+
10
+ runtime_options[:actions] = actions.empty? ? %w[index] : actions
11
+ runtime_options[:base_dest_folder] = "app/parts"
12
+ super( [name], runtime_options )
13
+ end
14
+
15
+ def self.superclass
16
+ RubiGen::Base
17
+ end
18
+
19
+ protected
20
+ def banner
21
+ <<-EOS
22
+ Creates a Merb part_controller
23
+
24
+ USAGE: #{$0} #{spec.name} name"
25
+ EOS
26
+ end
27
+ end
@@ -0,0 +1,8 @@
1
+ class <%= class_name %>Part < Merb::PartController
2
+ <% actions.each do |action| -%>
3
+
4
+ def <%= action %>
5
+ render
6
+ end
7
+ <% end -%>
8
+ end
@@ -0,0 +1,5 @@
1
+ module Merb
2
+ module <%= class_name %>PartHelper
3
+
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ <h1><%= class_name %>Part controller, index action</h1>
2
+
3
+ <p>Edit this file in <tt>app/parts/views/<%= file_name %>/index.html.erb</tt></p>
@@ -27,7 +27,7 @@ class MerbControllerTestGenerator < RubiGen::Base
27
27
  # Setup the view stubs for each view
28
28
  @template_actions.each do |the_action|
29
29
  template_name = "#{the_action}.html.#{@engine}"
30
- if File.exists?(File.join(MERB_ROOT, "app", "views", file_name, template_name))
30
+ if File.exists?(File.join(Merb.root, "app", "views", file_name, template_name))
31
31
  m.template "#{the_action}_spec.rb", "spec/views/#{file_name}/#{the_action}_html_spec.rb"
32
32
  end
33
33
  end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.join(File.dirname(__FILE__), '..')
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :rspec]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.join(File.dirname(__FILE__), '..')
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :rspec]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -32,6 +32,14 @@ class Bar < Merb::Controller
32
32
  "#{a} #{b} #{c}"
33
33
  end
34
34
 
35
+ def bat(a, b = false)
36
+ "#{a} #{b}"
37
+ end
38
+
39
+ def bam(a, b = nil)
40
+ "#{a} #{b.inspect}"
41
+ end
42
+
35
43
  end
36
44
 
37
45
  class Baz < Merb::Controller
@@ -224,4 +232,4 @@ class Profile < Merb::Controller
224
232
  end
225
233
 
226
234
  # If this throws an error, it's because parameterized args are somehow borked
227
- Merb::Server.load_application
235
+ Merb::BootLoader.load_application