merb-core 0.9.2 → 0.9.3

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.
Files changed (104) hide show
  1. data/Rakefile +61 -11
  2. data/bin/merb +5 -1
  3. data/lib/merb-core.rb +202 -25
  4. data/lib/merb-core/autoload.rb +19 -17
  5. data/lib/merb-core/bootloader.rb +84 -71
  6. data/lib/merb-core/config.rb +19 -14
  7. data/lib/merb-core/controller/abstract_controller.rb +16 -17
  8. data/lib/merb-core/controller/exceptions.rb +115 -70
  9. data/lib/merb-core/controller/merb_controller.rb +62 -38
  10. data/lib/merb-core/controller/mime.rb +1 -1
  11. data/lib/merb-core/controller/mixins/authentication.rb +87 -0
  12. data/lib/merb-core/controller/mixins/controller.rb +16 -15
  13. data/lib/merb-core/controller/mixins/render.rb +113 -19
  14. data/lib/merb-core/controller/mixins/responder.rb +8 -2
  15. data/lib/merb-core/controller/template.rb +1 -1
  16. data/lib/merb-core/core_ext.rb +1 -0
  17. data/lib/merb-core/core_ext/class.rb +113 -6
  18. data/lib/merb-core/core_ext/hash.rb +43 -39
  19. data/lib/merb-core/core_ext/kernel.rb +75 -38
  20. data/lib/merb-core/core_ext/mash.rb +4 -4
  21. data/lib/merb-core/core_ext/object.rb +18 -7
  22. data/lib/merb-core/core_ext/set.rb +9 -4
  23. data/lib/merb-core/core_ext/string.rb +29 -9
  24. data/lib/merb-core/core_ext/time.rb +13 -0
  25. data/lib/merb-core/dispatch/cookies.rb +1 -2
  26. data/lib/merb-core/dispatch/dispatcher.rb +18 -10
  27. data/lib/merb-core/dispatch/exceptions.html.erb +1 -1
  28. data/lib/merb-core/dispatch/request.rb +3 -0
  29. data/lib/merb-core/dispatch/router.rb +10 -7
  30. data/lib/merb-core/dispatch/router/behavior.rb +36 -27
  31. data/lib/merb-core/dispatch/router/route.rb +7 -2
  32. data/lib/merb-core/dispatch/session/cookie.rb +4 -4
  33. data/lib/merb-core/dispatch/session/memcached.rb +17 -5
  34. data/lib/merb-core/logger.rb +2 -2
  35. data/lib/merb-core/plugins.rb +16 -4
  36. data/lib/merb-core/rack/adapter/ebb.rb +4 -1
  37. data/lib/merb-core/rack/adapter/evented_mongrel.rb +2 -0
  38. data/lib/merb-core/rack/adapter/fcgi.rb +1 -0
  39. data/lib/merb-core/rack/adapter/mongrel.rb +1 -0
  40. data/lib/merb-core/rack/adapter/runner.rb +1 -0
  41. data/lib/merb-core/rack/adapter/thin.rb +3 -1
  42. data/lib/merb-core/rack/adapter/webrick.rb +1 -0
  43. data/lib/merb-core/rack/application.rb +17 -1
  44. data/lib/merb-core/server.rb +78 -28
  45. data/lib/merb-core/test/helpers/multipart_request_helper.rb +3 -3
  46. data/lib/merb-core/test/helpers/request_helper.rb +81 -27
  47. data/lib/merb-core/test/helpers/view_helper.rb +1 -1
  48. data/lib/merb-core/test/matchers/controller_matchers.rb +55 -5
  49. data/lib/merb-core/test/matchers/route_matchers.rb +8 -17
  50. data/lib/merb-core/test/matchers/view_matchers.rb +53 -11
  51. data/lib/merb-core/test/run_specs.rb +22 -14
  52. data/lib/merb-core/test/tasks/spectasks.rb +54 -33
  53. data/lib/merb-core/vendor/facets/inflect.rb +91 -2
  54. data/lib/merb-core/version.rb +2 -2
  55. data/spec/private/config/config_spec.rb +54 -26
  56. data/spec/private/core_ext/class_spec.rb +22 -0
  57. data/spec/private/core_ext/hash_spec.rb +70 -54
  58. data/spec/private/core_ext/kernel_spec.rb +149 -14
  59. data/spec/private/core_ext/object_spec.rb +92 -10
  60. data/spec/private/core_ext/string_spec.rb +162 -4
  61. data/spec/private/core_ext/time_spec.rb +16 -0
  62. data/spec/private/dispatch/bootloader_spec.rb +24 -0
  63. data/spec/private/dispatch/fixture/app/views/exeptions/client_error.html.erb +1 -1
  64. data/spec/private/dispatch/fixture/app/views/exeptions/internal_server_error.html.erb +1 -1
  65. data/spec/private/dispatch/fixture/app/views/exeptions/not_acceptable.html.erb +1 -1
  66. data/spec/private/dispatch/fixture/app/views/exeptions/not_found.html.erb +1 -1
  67. data/spec/private/dispatch/fixture/config/black_hole.rb +12 -0
  68. data/spec/private/dispatch/fixture/log/merb_test.log +138 -0
  69. data/spec/private/plugins/plugin_spec.rb +79 -8
  70. data/spec/private/rack/application_spec.rb +1 -1
  71. data/spec/public/abstract_controller/controllers/filters.rb +26 -0
  72. data/spec/public/abstract_controller/controllers/helpers.rb +2 -2
  73. data/spec/public/abstract_controller/controllers/partial.rb +2 -2
  74. data/spec/public/abstract_controller/controllers/render.rb +16 -4
  75. data/spec/public/abstract_controller/filter_spec.rb +8 -0
  76. data/spec/public/abstract_controller/render_spec.rb +12 -0
  77. data/spec/public/controller/authentication_spec.rb +103 -0
  78. data/spec/public/controller/base_spec.rb +4 -3
  79. data/spec/public/controller/controllers/authentication.rb +47 -0
  80. data/spec/public/controller/controllers/base.rb +1 -0
  81. data/spec/public/controller/controllers/display.rb +30 -0
  82. data/spec/public/controller/controllers/views/layout/custom_arg.html.erb +1 -0
  83. data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template_argument/index.html.erb +1 -0
  84. data/spec/public/controller/display_spec.rb +17 -0
  85. data/spec/public/controller/spec_helper.rb +1 -0
  86. data/spec/public/controller/url_spec.rb +25 -7
  87. data/spec/public/core/merb_core_spec.rb +34 -0
  88. data/spec/public/directory_structure/directory/app/controllers/custom.rb +2 -2
  89. data/spec/public/directory_structure/directory/log/merb_test.log +48 -0
  90. data/spec/public/logger/logger_spec.rb +10 -4
  91. data/spec/public/reloading/directory/app/controllers/reload.rb +1 -1
  92. data/spec/public/reloading/directory/log/merb_test.log +13 -0
  93. data/spec/public/reloading/reload_spec.rb +23 -22
  94. data/spec/public/request/request_spec.rb +2 -0
  95. data/spec/public/router/nested_resources_spec.rb +7 -0
  96. data/spec/public/router/resources_spec.rb +46 -1
  97. data/spec/public/router/special_spec.rb +5 -1
  98. data/spec/public/test/controller_matchers_spec.rb +25 -1
  99. data/spec/public/test/controllers/spec_helper_controller.rb +8 -0
  100. data/spec/public/test/request_helper_spec.rb +52 -1
  101. data/spec/public/test/route_matchers_spec.rb +27 -25
  102. data/spec/public/test/view_helper_spec.rb +1 -1
  103. data/spec/public/test/view_matchers_spec.rb +148 -72
  104. metadata +23 -3
@@ -112,7 +112,7 @@ module Merb
112
112
  return @output unless @output.nil?
113
113
  return @output = DocumentOutput.new(@response_output) unless @response_output.nil?
114
114
 
115
- raise "The response output was not in it's usual places, please provide the output" if @controller.nil? || @controller.body.empty?
115
+ raise "The response output was not in its usual places, please provide the output" if @controller.nil? || @controller.body.empty?
116
116
  @response_output = @controller.body
117
117
  @output = DocumentOutput.new(@controller.body)
118
118
  end
@@ -57,7 +57,7 @@ module Merb::Test::Rspec::ControllerMatchers
57
57
  def failure_message
58
58
  msg = "expected #{inspect_target} to redirect to <#{@expected}>, but "
59
59
  if @redirected
60
- msg << "was <#{target_location}>"
60
+ msg << "was <#{target_location}>"
61
61
  else
62
62
  msg << "there was no redirection"
63
63
  end
@@ -158,13 +158,51 @@ module Merb::Test::Rspec::ControllerMatchers
158
158
  end
159
159
  end
160
160
 
161
+ class Provide
162
+
163
+ # === Parameters
164
+ # expected<Symbol>:: A format to check
165
+ def initialize(expected)
166
+ @expected = expected
167
+ end
168
+
169
+ # ==== Parameters
170
+ # target<Symbol>::
171
+ # A ControllerClass or controller_instance
172
+ #
173
+ # ==== Returns
174
+ # Boolean:: True if the formats provided by the target controller/class include the expected
175
+ def matches?(target)
176
+ @target = target
177
+ provided_formats.include?( @expected )
178
+ end
179
+
180
+ # ==== Returns
181
+ # String:: The failure message.
182
+ def failure_message
183
+ "expected #{@target.name} to provide #{@expected}, but it doesn't"
184
+ end
185
+
186
+ # ==== Returns
187
+ # String:: The failure message to be displayed in negative matches.
188
+ def negative_failure_message
189
+ "expected #{@target.name} not to provide #{@expected}, but it does"
190
+ end
191
+
192
+ # ==== Returns
193
+ # Array[Symbol]:: The formats the expected provides
194
+ def provided_formats
195
+ @target.class_provided_formats
196
+ end
197
+ end
198
+
161
199
  # Passes if the target was redirected, or the target is a redirection (300
162
200
  # level) response code.
163
201
  #
164
202
  # ==== Examples
165
203
  # # Passes if the controller was redirected
166
204
  # controller.should redirect
167
- #
205
+ #
168
206
  # # Also works if the target is the response code
169
207
  # controller.status.should redirect
170
208
  #
@@ -206,7 +244,7 @@ module Merb::Test::Rspec::ControllerMatchers
206
244
  # ==== Examples
207
245
  # # Passes if the controller call was successful
208
246
  # controller.should respond_successfully
209
- #
247
+ #
210
248
  # # Also works if the target is the response code
211
249
  # controller.status.should respond_successfully
212
250
  #
@@ -234,7 +272,7 @@ module Merb::Test::Rspec::ControllerMatchers
234
272
  # ==== Examples
235
273
  # # Passes if the controller call was unknown or not understood
236
274
  # controller.should be_missing
237
- #
275
+ #
238
276
  # # Also passes if the target is a response code
239
277
  # controller.status.should be_missing
240
278
  #
@@ -266,4 +304,16 @@ module Merb::Test::Rspec::ControllerMatchers
266
304
  end
267
305
 
268
306
  alias_method :be_client_error, :be_missing
269
- end
307
+
308
+ # Passes if the controller actually provides the target format
309
+ #
310
+ # === Parameters
311
+ # expected<Symbol>:: A format to check
312
+ #
313
+ # ==== Examples
314
+ # ControllerClass.should provide( :html )
315
+ # controller_instance.should provide( :xml )
316
+ def provide( expected )
317
+ Provide.new( expected )
318
+ end
319
+ end
@@ -19,9 +19,9 @@ module Merb::Test::Rspec::RouteMatchers
19
19
  def matches?(target)
20
20
  @target_env = target.dup
21
21
  @target_controller, @target_action = @target_env.delete(:controller).to_s, @target_env.delete(:action).to_s
22
-
22
+
23
23
  @target_controller = "#{target.delete(:namespace)}::#{@target_controller}" if target.has_key?(:namespace)
24
-
24
+
25
25
  @expected_controller.snake_case == @target_controller.snake_case && @expected_action == @target_action && match_parameters(@target_env)
26
26
  end
27
27
 
@@ -49,29 +49,20 @@ module Merb::Test::Rspec::RouteMatchers
49
49
  # with the key :id set to parameters.to_param.
50
50
  def with(parameters)
51
51
  @paramter_matcher = ParameterMatcher.new(parameters)
52
-
52
+
53
53
  self
54
54
  end
55
55
 
56
56
  # ==== Returns
57
57
  # String:: The failure message.
58
58
  def failure_message
59
- "expected the request to route to #{camelize(@expected_controller)}##{@expected_action}, but was #{camelize(@target_controller)}##{@target_action}"
59
+ "expected the request to route to #{@expected_controller.camel_case}##{@expected_action}, but was #{@target_controller.camel_case}##{@target_action}"
60
60
  end
61
-
61
+
62
62
  # ==== Returns
63
63
  # String:: The failure message to be displayed in negative matches.
64
64
  def negative_failure_message
65
- "expected the request not to route to #{camelize(@expected_controller)}##{@expected_action}, but it did"
66
- end
67
-
68
- # ==== Parameters
69
- # word<~to_s>:: The word to camelize.
70
- #
71
- # ==== Returns
72
- # String:: The word camelized.
73
- def camelize(word)
74
- word.to_s.gsub(/^[a-z]|(\_[a-z])/) { |a| a.upcase.gsub("_", "") }
65
+ "expected the request not to route to #{@expected_controller.camel_case}##{@expected_action}, but it did"
75
66
  end
76
67
  end
77
68
 
@@ -98,7 +89,7 @@ module Merb::Test::Rspec::RouteMatchers
98
89
  # Boolean:: True if the route parameters match the expected ones.
99
90
  def matches?(parameter_hash)
100
91
  @actual = parameter_hash.dup.except(:controller, :action)
101
-
92
+
102
93
  @expected.all? {|(k, v)| @actual.has_key?(k) && @actual[k] == v}
103
94
  end
104
95
 
@@ -133,4 +124,4 @@ module Merb::Test::Rspec::RouteMatchers
133
124
  def route_to(klass_or_name, action)
134
125
  RouteToMatcher.new(klass_or_name, action)
135
126
  end
136
- end
127
+ end
@@ -115,15 +115,16 @@ module Merb::Test::Rspec::ViewMatchers
115
115
  @errors[0]
116
116
  end
117
117
  end
118
-
118
+
119
119
  class HasTag
120
-
120
+
121
121
  # ==== Parameters
122
122
  # tag<~to_s>:: The tag to look for.
123
123
  # attributes<Hash>:: Attributes for the tag (see below).
124
- def initialize(tag, attributes = {})
124
+ def initialize(tag, attributes = {}, &blk)
125
125
  @tag, @attributes = tag, attributes
126
126
  @id, @class = @attributes.delete(:id), @attributes.delete(:class)
127
+ @blk = blk
127
128
  end
128
129
 
129
130
  # ==== Parameters
@@ -141,14 +142,13 @@ module Merb::Test::Rspec::ViewMatchers
141
142
  else
142
143
  Hpricot.parse(stringlike)
143
144
  end
145
+
146
+ @blk = blk unless blk.nil?
144
147
 
145
- if block_given?
148
+ unless @blk.nil?
146
149
  !@document.search(selector).select do |ele|
147
- begin
148
- blk.call(ele)
149
- rescue Spec::Expectations::ExpectationNotMetError
150
- false
151
- end
150
+ @blk.call ele
151
+ true
152
152
  end.empty?
153
153
  else
154
154
  !@document.search(selector).empty?
@@ -232,6 +232,44 @@ module Merb::Test::Rspec::ViewMatchers
232
232
  end
233
233
  end
234
234
 
235
+ class HasContent
236
+ def initialize(content)
237
+ @content = content
238
+ end
239
+
240
+ def matches?(element)
241
+ @element = element
242
+
243
+ case @content
244
+ when String
245
+ @element.contains?(@content)
246
+ when Regexp
247
+ @element.matches?(@content)
248
+ end
249
+ end
250
+
251
+ # ==== Returns
252
+ # String:: The failure message.
253
+ def failure_message
254
+ "expected the following element's content to #{content_message}:\n#{@element.inner_content}"
255
+ end
256
+
257
+ # ==== Returns
258
+ # String:: The failure message to be displayed in negative matches.
259
+ def negative_failure_message
260
+ "expected the following element's content to not #{content_message}:\n#{@element.inner_content}"
261
+ end
262
+
263
+ def content_message
264
+ case @content
265
+ when String
266
+ "include \"#{@content}\""
267
+ when Regexp
268
+ "match #{@content.inspect}"
269
+ end
270
+ end
271
+ end
272
+
235
273
  # ==== Parameters
236
274
  # name<~to_s>:: The name of the tag to look for.
237
275
  # attrs<Hash>:: Attributes to look for in the tag (see below).
@@ -285,9 +323,13 @@ module Merb::Test::Rspec::ViewMatchers
285
323
  #
286
324
  # # Check for <div attr="val">
287
325
  # body.should have_tag(:div, :attr => :val)
288
- def have_tag(tag, attributes = {})
289
- HasTag.new(tag, attributes)
326
+ def have_tag(tag, attributes = {}, &blk)
327
+ HasTag.new(tag, attributes, &blk)
290
328
  end
291
329
 
292
330
  alias_method :with_tag, :have_tag
331
+
332
+ def contain(content)
333
+ HasContent.new(content)
334
+ end
293
335
  end
@@ -1,31 +1,38 @@
1
1
  require 'open3'
2
+ require 'benchmark'
2
3
 
3
4
  # Runs specs in all files matching the file pattern.
4
5
  #
5
6
  # ==== Parameters
6
7
  # globs<String, Array[String]>:: File patterns to look for.
7
8
  # spec_cmd<~to_s>:: The spec command. Defaults to "spec".
8
- def run_specs(globs, spec_cmd='spec')
9
+ # run_opts<String>:: Options to pass to spec commands, for instance,
10
+ # if you want to use profiling formatter.
11
+ def run_specs(globs, spec_cmd='spec', run_opts = "-c -f s")
9
12
  require "optparse"
10
13
  require "spec"
11
14
  globs = globs.is_a?(Array) ? globs : [globs]
12
15
  examples, failures, errors, pending = 0, 0, 0, 0
13
- globs.each do |glob|
14
- Dir[glob].each do |spec|
15
- response = Open3.popen3("#{spec_cmd} #{File.expand_path(spec)} -f s -c") do |i,o,e|
16
- while out = o.gets
17
- STDOUT.puts out
18
- STDOUT.flush
19
- if out =~ /\d+ example/
20
- e, f, p = out.match(/(\d+) examples?, (\d+) failures?(?:, (\d+) pending?)?/)[1..-1]
21
- examples += e.to_i; failures += f.to_i; pending += p.to_i
16
+
17
+ time = Benchmark.measure do
18
+ globs.each do |glob|
19
+ Dir[glob].each do |spec|
20
+ response = Open3.popen3("#{spec_cmd} #{File.expand_path(spec)} #{run_opts}") do |i,o,e|
21
+ while out = o.gets
22
+ STDOUT.puts out
23
+ STDOUT.flush
24
+ if out =~ /\d+ example/
25
+ e, f, p = out.match(/(\d+) examples?, (\d+) failures?(?:, (\d+) pending?)?/)[1..-1]
26
+ examples += e.to_i; failures += f.to_i; pending += p.to_i
27
+ end
22
28
  end
29
+ errors += 1 if e.is_a?(IO)
30
+ STDOUT.puts e.read if e.is_a?(IO)
23
31
  end
24
- errors += 1 if e.is_a?(IO)
25
- STDOUT.puts e.read if e.is_a?(IO)
26
32
  end
27
33
  end
28
34
  end
35
+
29
36
  puts
30
37
  puts "*** TOTALS ***"
31
38
  if failures == 0
@@ -33,6 +40,7 @@ def run_specs(globs, spec_cmd='spec')
33
40
  else
34
41
  print "\e[31m"
35
42
  end
36
- puts "#{examples} examples, #{failures} failures, #{errors} errors, #{pending} pending"
37
- print "\e[0m"
43
+ puts "#{examples} examples, #{failures} failures, #{errors} errors, #{pending} pending, #{sprintf("suite run in %3.3f seconds", time.real)}"
44
+ # TODO: we need to report pending examples all together
45
+ print "\e[0m"
38
46
  end
@@ -1,39 +1,60 @@
1
- desc "Run all specs"
2
- Spec::Rake::SpecTask.new('specs') do |t|
3
- t.spec_opts = ["--format", "specdoc", "--colour"]
4
- t.spec_files = Dir['spec/**/*_spec.rb'].sort
5
- end
1
+ desc "Run specs, run a specific spec with TASK=spec/path_to_spec.rb"
2
+ task :spec => [ "spec:default" ]
6
3
 
7
- desc "Run all model specs"
8
- Spec::Rake::SpecTask.new('model_specs') do |t|
9
- t.spec_opts = ["--format", "specdoc", "--colour"]
10
- t.spec_files = Dir['spec/models/**/*_spec.rb'].sort
11
- end
4
+ namespace :spec do
5
+ Spec::Rake::SpecTask.new('default') do |t|
6
+ t.spec_opts = ["--format", "specdoc", "--colour"]
7
+ if(ENV['TASK'])
8
+ t.spec_files = [ENV['TASK']]
9
+ else
10
+ t.spec_files = Dir['spec/**/*_spec.rb'].sort
11
+ end
12
+ end
12
13
 
13
- desc "Run all controller specs"
14
- Spec::Rake::SpecTask.new('controller_specs') do |t|
15
- t.spec_opts = ["--format", "specdoc", "--colour"]
16
- t.spec_files = Dir['spec/controllers/**/*_spec.rb'].sort
17
- end
14
+ desc "Run all model specs, run a spec for a specific Model with MODEL=MyModel"
15
+ Spec::Rake::SpecTask.new('model') do |t|
16
+ t.spec_opts = ["--format", "specdoc", "--colour"]
17
+ if(ENV['MODEL'])
18
+ t.spec_files = Dir["spec/models/**/#{ENV['MODEL']}_spec.rb"].sort
19
+ else
20
+ t.spec_files = Dir['spec/models/**/*_spec.rb'].sort
21
+ end
22
+ end
18
23
 
19
- desc "Run a specific spec with TASK=xxxx"
20
- Spec::Rake::SpecTask.new('spec') do |t|
21
- t.spec_opts = ["--format", "specdoc", "--colour"]
22
- t.libs = ['lib', 'server/lib' ]
23
- t.spec_files = ["spec/#{ENV['TASK']}_spec.rb"]
24
- end
24
+ desc "Run all controller specs, run a spec for a specific Controller with CONTROLLER=MyController"
25
+ Spec::Rake::SpecTask.new('controller') do |t|
26
+ t.spec_opts = ["--format", "specdoc", "--colour"]
27
+ if(ENV['CONTROLLER'])
28
+ t.spec_files = Dir["spec/controllers/**/#{ENV['CONTROLLER']}_spec.rb"].sort
29
+ else
30
+ t.spec_files = Dir['spec/controllers/**/*_spec.rb'].sort
31
+ end
32
+ end
33
+
34
+ desc "Run all view specs, run specs for a specific controller (and view) with CONTROLLER=MyController (VIEW=MyView)"
35
+ Spec::Rake::SpecTask.new('view') do |t|
36
+ t.spec_opts = ["--format", "specdoc", "--colour"]
37
+ if(ENV['CONTROLLER'] and ENV['VIEW'])
38
+ t.spec_files = Dir["spec/views/**/#{ENV['CONTROLLER']}/#{ENV['VIEW']}*_spec.rb"].sort
39
+ elsif(ENV['CONTROLLER'])
40
+ t.spec_files = Dir["spec/views/**/#{ENV['CONTROLLER']}/*_spec.rb"].sort
41
+ else
42
+ t.spec_files = Dir['spec/views/**/*_spec.rb'].sort
43
+ end
44
+ end
25
45
 
26
- desc "Run all specs output html"
27
- Spec::Rake::SpecTask.new('specs_html') do |t|
28
- t.spec_opts = ["--format", "html"]
29
- t.libs = ['lib', 'server/lib' ]
30
- t.spec_files = Dir['spec/**/*_spec.rb'].sort
31
- end
46
+ desc "Run all specs and output the result in html"
47
+ Spec::Rake::SpecTask.new('html') do |t|
48
+ t.spec_opts = ["--format", "html"]
49
+ t.libs = ['lib', 'server/lib' ]
50
+ t.spec_files = Dir['spec/**/*_spec.rb'].sort
51
+ end
32
52
 
33
- desc "RCov"
34
- Spec::Rake::SpecTask.new('rcov') do |t|
35
- t.spec_opts = ["--format", "specdoc", "--colour"]
36
- t.spec_files = Dir['spec/**/*_spec.rb'].sort
37
- t.libs = ['lib', 'server/lib' ]
38
- t.rcov = true
53
+ desc "Run specs and check coverage with rcov"
54
+ Spec::Rake::SpecTask.new('coverage') do |t|
55
+ t.spec_opts = ["--format", "specdoc", "--colour"]
56
+ t.spec_files = Dir['spec/**/*_spec.rb'].sort
57
+ t.libs = ['lib', 'server/lib' ]
58
+ t.rcov = true
59
+ end
39
60
  end
@@ -14,7 +14,24 @@ module English
14
14
  @plural_rules = []
15
15
 
16
16
  class << self
17
- # Define a general exception.
17
+ # Defines a general inflection exception case.
18
+ #
19
+ # ==== Parameters
20
+ # singular<String>::
21
+ # singular form of the word
22
+ # plural<String>::
23
+ # plural form of the word
24
+ #
25
+ # ==== Examples
26
+ #
27
+ # Here we define erratum/errata exception case:
28
+ #
29
+ # Language::English::Inflector.word "erratum", "errata"
30
+ #
31
+ # In case singular and plural forms are the same omit
32
+ # second argument on call:
33
+ #
34
+ # Language::English::Inflector.word 'information'
18
35
  def word(singular, plural=nil)
19
36
  plural = singular unless plural
20
37
  singular_word(singular, plural)
@@ -22,27 +39,83 @@ module English
22
39
  end
23
40
 
24
41
  # Define a singularization exception.
42
+ #
43
+ # ==== Parameters
44
+ # singular<String>::
45
+ # singular form of the word
46
+ # plural<String>::
47
+ # plural form of the word
25
48
  def singular_word(singular, plural)
26
49
  @singular_of[plural] = singular
27
50
  end
28
51
 
29
52
  # Define a pluralization exception.
53
+ #
54
+ # ==== Parameters
55
+ # singular<String>::
56
+ # singular form of the word
57
+ # plural<String>::
58
+ # plural form of the word
30
59
  def plural_word(singular, plural)
31
60
  @plural_of[singular] = plural
32
61
  end
33
62
 
34
63
  # Define a general rule.
64
+ #
65
+ # ==== Parameters
66
+ # singular<String>::
67
+ # ending of the word in singular form
68
+ # plural<String>::
69
+ # ending of the word in plural form
70
+ #
71
+ # ==== Examples
72
+ # Once the following rule is defined:
73
+ # Language::English::Inflector.rule 'y', 'ies'
74
+ #
75
+ # You can see the following results:
76
+ # irb> "fly".plural
77
+ # => flies
78
+ # irb> "cry".plural
79
+ # => cries
35
80
  def rule(singular, plural)
36
81
  singular_rule(singular, plural)
37
82
  plural_rule(singular, plural)
38
83
  end
39
84
 
40
85
  # Define a singularization rule.
86
+ #
87
+ # ==== Parameters
88
+ # singular<String>::
89
+ # ending of the word in singular form
90
+ # plural<String>::
91
+ # ending of the word in plural form
92
+ #
93
+ # ==== Examples
94
+ # Once the following rule is defined:
95
+ # Language::English::Inflector.singular_rule 'o', 'oes'
96
+ #
97
+ # You can see the following results:
98
+ # irb> "heroes".singular
99
+ # => hero
41
100
  def singular_rule(singular, plural)
42
101
  @singular_rules << [singular, plural]
43
102
  end
44
103
 
45
104
  # Define a plurualization rule.
105
+ #
106
+ # ==== Parameters
107
+ # singular<String>::
108
+ # ending of the word in singular form
109
+ # plural<String>::
110
+ # ending of the word in plural form
111
+ #
112
+ # ==== Examples
113
+ # Once the following rule is defined:
114
+ # Language::English::Inflector.singular_rule 'fe', 'ves'
115
+ #
116
+ # You can see the following results:
117
+ # irb> "wife".plural
118
+ # => wives
46
119
  def plural_rule(singular, plural)
47
120
  @plural_rules << [singular, plural]
48
121
  end
@@ -80,6 +153,14 @@ module English
80
153
  # "boys".singular #=> boy
81
154
  # "tomatoes".singular #=> tomato
82
155
  #
156
+ # ==== Parameters
157
+ # word<String>:: word to singularize
158
+ #
159
+ # ==== Returns
160
+ # <String>:: singularized form of word
161
+ #
162
+ # ==== Notes
163
+ # Aliased as singularize (a Railism)
83
164
  def singular(word)
84
165
  if result = singular_of[word]
85
166
  return result.dup
@@ -100,6 +181,14 @@ module English
100
181
  # "boy".plural #=> boys
101
182
  # "tomato".plural #=> tomatoes
102
183
  #
184
+ # ==== Parameters
185
+ # word<String>:: word to pluralize
186
+ #
187
+ # ==== Returns
188
+ # <String>:: pluralized form of word
189
+ #
190
+ # ==== Notes
191
+ # Aliased as pluralize (a Railism)
103
192
  def plural(word)
104
193
  if result = plural_of[word]
105
194
  return result.dup
@@ -208,4 +297,4 @@ class String
208
297
  Language::English::Inflect.plural(self)
209
298
  end
210
299
  alias_method(:pluralize, :plural)
211
- end
300
+ end