merb-core 0.9.2
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.
- data/LICENSE +20 -0
- data/README +21 -0
- data/Rakefile +285 -0
- data/TODO +0 -0
- data/bin/merb +8 -0
- data/bin/merb-specs +5 -0
- data/docs/bootloading.dox +57 -0
- data/docs/documentation_standards +40 -0
- data/docs/new_render_api +51 -0
- data/lib/merb-core.rb +304 -0
- data/lib/merb-core/autoload.rb +29 -0
- data/lib/merb-core/bootloader.rb +601 -0
- data/lib/merb-core/config.rb +284 -0
- data/lib/merb-core/constants.rb +43 -0
- data/lib/merb-core/controller/abstract_controller.rb +531 -0
- data/lib/merb-core/controller/exceptions.rb +257 -0
- data/lib/merb-core/controller/merb_controller.rb +214 -0
- data/lib/merb-core/controller/mime.rb +88 -0
- data/lib/merb-core/controller/mixins/controller.rb +262 -0
- data/lib/merb-core/controller/mixins/render.rb +324 -0
- data/lib/merb-core/controller/mixins/responder.rb +464 -0
- data/lib/merb-core/controller/template.rb +205 -0
- data/lib/merb-core/core_ext.rb +12 -0
- data/lib/merb-core/core_ext/class.rb +192 -0
- data/lib/merb-core/core_ext/hash.rb +422 -0
- data/lib/merb-core/core_ext/kernel.rb +304 -0
- data/lib/merb-core/core_ext/mash.rb +154 -0
- data/lib/merb-core/core_ext/object.rb +136 -0
- data/lib/merb-core/core_ext/object_space.rb +14 -0
- data/lib/merb-core/core_ext/rubygems.rb +28 -0
- data/lib/merb-core/core_ext/set.rb +41 -0
- data/lib/merb-core/core_ext/string.rb +69 -0
- data/lib/merb-core/dispatch/cookies.rb +92 -0
- data/lib/merb-core/dispatch/dispatcher.rb +233 -0
- data/lib/merb-core/dispatch/exceptions.html.erb +297 -0
- data/lib/merb-core/dispatch/request.rb +560 -0
- data/lib/merb-core/dispatch/router.rb +141 -0
- data/lib/merb-core/dispatch/router/behavior.rb +777 -0
- data/lib/merb-core/dispatch/router/cached_proc.rb +52 -0
- data/lib/merb-core/dispatch/router/route.rb +212 -0
- data/lib/merb-core/dispatch/session.rb +28 -0
- data/lib/merb-core/dispatch/session/cookie.rb +166 -0
- data/lib/merb-core/dispatch/session/memcached.rb +161 -0
- data/lib/merb-core/dispatch/session/memory.rb +234 -0
- data/lib/merb-core/gem_ext/erubis.rb +19 -0
- data/lib/merb-core/logger.rb +230 -0
- data/lib/merb-core/plugins.rb +25 -0
- data/lib/merb-core/rack.rb +15 -0
- data/lib/merb-core/rack/adapter.rb +42 -0
- data/lib/merb-core/rack/adapter/ebb.rb +22 -0
- data/lib/merb-core/rack/adapter/evented_mongrel.rb +24 -0
- data/lib/merb-core/rack/adapter/fcgi.rb +16 -0
- data/lib/merb-core/rack/adapter/irb.rb +108 -0
- data/lib/merb-core/rack/adapter/mongrel.rb +25 -0
- data/lib/merb-core/rack/adapter/runner.rb +27 -0
- data/lib/merb-core/rack/adapter/thin.rb +27 -0
- data/lib/merb-core/rack/adapter/webrick.rb +35 -0
- data/lib/merb-core/rack/application.rb +77 -0
- data/lib/merb-core/rack/handler/mongrel.rb +97 -0
- data/lib/merb-core/server.rb +184 -0
- data/lib/merb-core/test.rb +10 -0
- data/lib/merb-core/test/helpers.rb +9 -0
- data/lib/merb-core/test/helpers/controller_helper.rb +8 -0
- data/lib/merb-core/test/helpers/multipart_request_helper.rb +175 -0
- data/lib/merb-core/test/helpers/request_helper.rb +257 -0
- data/lib/merb-core/test/helpers/route_helper.rb +33 -0
- data/lib/merb-core/test/helpers/view_helper.rb +121 -0
- data/lib/merb-core/test/matchers.rb +9 -0
- data/lib/merb-core/test/matchers/controller_matchers.rb +269 -0
- data/lib/merb-core/test/matchers/route_matchers.rb +136 -0
- data/lib/merb-core/test/matchers/view_matchers.rb +293 -0
- data/lib/merb-core/test/run_specs.rb +38 -0
- data/lib/merb-core/test/tasks/spectasks.rb +39 -0
- data/lib/merb-core/test/test_ext/hpricot.rb +32 -0
- data/lib/merb-core/test/test_ext/object.rb +14 -0
- data/lib/merb-core/vendor/facets.rb +2 -0
- data/lib/merb-core/vendor/facets/dictionary.rb +433 -0
- data/lib/merb-core/vendor/facets/inflect.rb +211 -0
- data/lib/merb-core/version.rb +11 -0
- data/spec/private/config/adapter_spec.rb +32 -0
- data/spec/private/config/config_spec.rb +139 -0
- data/spec/private/config/environment_spec.rb +13 -0
- data/spec/private/config/spec_helper.rb +1 -0
- data/spec/private/core_ext/hash_spec.rb +506 -0
- data/spec/private/core_ext/kernel_spec.rb +46 -0
- data/spec/private/core_ext/object_spec.rb +39 -0
- data/spec/private/core_ext/set_spec.rb +26 -0
- data/spec/private/core_ext/string_spec.rb +9 -0
- data/spec/private/dispatch/cookies_spec.rb +107 -0
- data/spec/private/dispatch/dispatch_spec.rb +26 -0
- data/spec/private/dispatch/fixture/app/controllers/application.rb +4 -0
- data/spec/private/dispatch/fixture/app/controllers/exceptions.rb +27 -0
- data/spec/private/dispatch/fixture/app/controllers/foo.rb +21 -0
- data/spec/private/dispatch/fixture/app/helpers/global_helpers.rb +8 -0
- data/spec/private/dispatch/fixture/app/views/exeptions/client_error.html.erb +37 -0
- data/spec/private/dispatch/fixture/app/views/exeptions/internal_server_error.html.erb +216 -0
- data/spec/private/dispatch/fixture/app/views/exeptions/not_acceptable.html.erb +38 -0
- data/spec/private/dispatch/fixture/app/views/exeptions/not_found.html.erb +40 -0
- data/spec/private/dispatch/fixture/app/views/foo/bar.html.erb +0 -0
- data/spec/private/dispatch/fixture/app/views/layout/application.html.erb +11 -0
- data/spec/private/dispatch/fixture/config/environments/development.rb +6 -0
- data/spec/private/dispatch/fixture/config/environments/production.rb +5 -0
- data/spec/private/dispatch/fixture/config/environments/test.rb +6 -0
- data/spec/private/dispatch/fixture/config/init.rb +45 -0
- data/spec/private/dispatch/fixture/config/rack.rb +1 -0
- data/spec/private/dispatch/fixture/config/router.rb +35 -0
- data/spec/private/dispatch/fixture/log/development.log +1 -0
- data/spec/private/dispatch/fixture/log/merb.4000.pid +1 -0
- data/spec/private/dispatch/fixture/log/merb_test.log +2040 -0
- data/spec/private/dispatch/fixture/log/production.log +1 -0
- data/spec/private/dispatch/fixture/merb.4000.pid +1 -0
- data/spec/private/dispatch/fixture/public/images/merb.jpg +0 -0
- data/spec/private/dispatch/fixture/public/merb.fcgi +4 -0
- data/spec/private/dispatch/fixture/public/stylesheets/master.css +119 -0
- data/spec/private/dispatch/route_params_spec.rb +24 -0
- data/spec/private/dispatch/spec_helper.rb +1 -0
- data/spec/private/plugins/plugin_spec.rb +81 -0
- data/spec/private/rack/application_spec.rb +43 -0
- data/spec/public/DEFINITIONS +11 -0
- data/spec/public/abstract_controller/controllers/alt_views/layout/application.erb +1 -0
- data/spec/public/abstract_controller/controllers/alt_views/layout/merb/test/fixtures/abstract/render_string_controller_layout.erb +1 -0
- data/spec/public/abstract_controller/controllers/alt_views/layout/merb/test/fixtures/abstract/render_template_controller_layout.erb +1 -0
- data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/display_object_with_multiple_roots/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/display_object_with_multiple_roots/show.erb +1 -0
- data/spec/public/abstract_controller/controllers/alt_views/merb/test/fixtures/abstract/render_template_multiple_roots/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/alt_views/partial/basic_partial_with_multiple_roots/_partial.erb +1 -0
- data/spec/public/abstract_controller/controllers/alt_views/render_template_multiple_roots_and_custom_location/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/alt_views/render_template_multiple_roots_inherited/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/display.rb +54 -0
- data/spec/public/abstract_controller/controllers/filters.rb +167 -0
- data/spec/public/abstract_controller/controllers/helpers.rb +31 -0
- data/spec/public/abstract_controller/controllers/partial.rb +106 -0
- data/spec/public/abstract_controller/controllers/render.rb +86 -0
- data/spec/public/abstract_controller/controllers/views/helpers/capture/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/helpers/concat/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/layout/alt.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/layout/custom.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/display_object/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/display_object_with_action/new.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_app_layout/index.erb +0 -0
- data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_custom_layout/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_multiple_roots/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/merb/test/fixtures/abstract/render_template_multiple_roots/show.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/another_directory/_partial.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/basic_partial/_partial.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/basic_partial/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/basic_partial_with_multiple_roots/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/nested_partial/_first.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/nested_partial/_second.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/nested_partial/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_in_another_directory/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_both/_collection.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_both/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections/_collection.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_as/_collection.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_collections_and_as/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_locals/_variables.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_locals/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_with_and_locals/_both.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/partial_with_with_and_locals/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/with_as_partial/_with_partial.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/with_as_partial/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/with_nil_partial/_with_partial.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/with_nil_partial/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/with_partial/_with_partial.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/partial/with_partial/index.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/test_display/foo.html.erb +1 -0
- data/spec/public/abstract_controller/controllers/views/test_render/foo.html.erb +0 -0
- data/spec/public/abstract_controller/controllers/views/wonderful/index.erb +1 -0
- data/spec/public/abstract_controller/display_spec.rb +33 -0
- data/spec/public/abstract_controller/filter_spec.rb +80 -0
- data/spec/public/abstract_controller/helper_spec.rb +13 -0
- data/spec/public/abstract_controller/partial_spec.rb +53 -0
- data/spec/public/abstract_controller/render_spec.rb +70 -0
- data/spec/public/abstract_controller/spec_helper.rb +27 -0
- data/spec/public/boot_loader/boot_loader_spec.rb +33 -0
- data/spec/public/boot_loader/spec_helper.rb +1 -0
- data/spec/public/controller/base_spec.rb +31 -0
- data/spec/public/controller/controllers/base.rb +41 -0
- data/spec/public/controller/controllers/display.rb +40 -0
- data/spec/public/controller/controllers/responder.rb +67 -0
- data/spec/public/controller/controllers/url.rb +7 -0
- data/spec/public/controller/controllers/views/layout/custom.html.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_provides/index.html.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/class_provides/index.xml.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/display_with_template/index.html.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/html_default/index.html.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/layout/custom.html.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/local_provides/index.html.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/local_provides/index.xml.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/multi_provides/index.html.erb +1 -0
- data/spec/public/controller/controllers/views/merb/test/fixtures/controllers/multi_provides/index.js.erb +1 -0
- data/spec/public/controller/display_spec.rb +34 -0
- data/spec/public/controller/log/merb.4000.pid +1 -0
- data/spec/public/controller/responder_spec.rb +95 -0
- data/spec/public/controller/spec_helper.rb +9 -0
- data/spec/public/controller/url_spec.rb +152 -0
- data/spec/public/directory_structure/directory/app/controllers/application.rb +3 -0
- data/spec/public/directory_structure/directory/app/controllers/base.rb +13 -0
- data/spec/public/directory_structure/directory/app/controllers/custom.rb +19 -0
- data/spec/public/directory_structure/directory/app/views/base/template.html.erb +1 -0
- data/spec/public/directory_structure/directory/app/views/wonderful/template.erb +1 -0
- data/spec/public/directory_structure/directory/config/router.rb +3 -0
- data/spec/public/directory_structure/directory/log/merb.4000.pid +1 -0
- data/spec/public/directory_structure/directory/log/merb_test.log +265 -0
- data/spec/public/directory_structure/directory/merb.4000.pid +1 -0
- data/spec/public/directory_structure/directory_spec.rb +44 -0
- data/spec/public/logger/logger_spec.rb +175 -0
- data/spec/public/logger/spec_helper.rb +1 -0
- data/spec/public/reloading/directory/app/controllers/application.rb +3 -0
- data/spec/public/reloading/directory/app/controllers/reload.rb +6 -0
- data/spec/public/reloading/directory/config/init.rb +2 -0
- data/spec/public/reloading/directory/log/merb.4000.pid +1 -0
- data/spec/public/reloading/directory/log/merb_test.log +59 -0
- data/spec/public/reloading/directory/merb.4000.pid +1 -0
- data/spec/public/reloading/reload_spec.rb +80 -0
- data/spec/public/request/multipart_spec.rb +15 -0
- data/spec/public/request/request_spec.rb +207 -0
- data/spec/public/router/default_spec.rb +21 -0
- data/spec/public/router/deferred_spec.rb +22 -0
- data/spec/public/router/namespace_spec.rb +113 -0
- data/spec/public/router/nested_resources_spec.rb +34 -0
- data/spec/public/router/resource_spec.rb +45 -0
- data/spec/public/router/resources_spec.rb +57 -0
- data/spec/public/router/spec_helper.rb +72 -0
- data/spec/public/router/special_spec.rb +44 -0
- data/spec/public/router/string_spec.rb +61 -0
- data/spec/public/template/template_spec.rb +92 -0
- data/spec/public/template/templates/error.html.erb +2 -0
- data/spec/public/template/templates/template.html.erb +1 -0
- data/spec/public/template/templates/template.html.myt +1 -0
- data/spec/public/test/controller_matchers_spec.rb +378 -0
- data/spec/public/test/controllers/controller_assertion_mock.rb +7 -0
- data/spec/public/test/controllers/dispatch_controller.rb +11 -0
- data/spec/public/test/controllers/spec_helper_controller.rb +30 -0
- data/spec/public/test/multipart_request_helper_spec.rb +159 -0
- data/spec/public/test/multipart_upload_text_file.txt +1 -0
- data/spec/public/test/request_helper_spec.rb +153 -0
- data/spec/public/test/route_helper_spec.rb +54 -0
- data/spec/public/test/route_matchers_spec.rb +133 -0
- data/spec/public/test/view_helper_spec.rb +96 -0
- data/spec/public/test/view_matchers_spec.rb +107 -0
- data/spec/spec_helper.rb +71 -0
- metadata +488 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
module Language
|
|
2
|
+
|
|
3
|
+
module English
|
|
4
|
+
|
|
5
|
+
# = English Nouns Number Inflection.
|
|
6
|
+
#
|
|
7
|
+
# This module provides english singular <-> plural noun inflections.
|
|
8
|
+
module Inflect
|
|
9
|
+
|
|
10
|
+
@singular_of = {}
|
|
11
|
+
@plural_of = {}
|
|
12
|
+
|
|
13
|
+
@singular_rules = []
|
|
14
|
+
@plural_rules = []
|
|
15
|
+
|
|
16
|
+
class << self
|
|
17
|
+
# Define a general exception.
|
|
18
|
+
def word(singular, plural=nil)
|
|
19
|
+
plural = singular unless plural
|
|
20
|
+
singular_word(singular, plural)
|
|
21
|
+
plural_word(singular, plural)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Define a singularization exception.
|
|
25
|
+
def singular_word(singular, plural)
|
|
26
|
+
@singular_of[plural] = singular
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Define a pluralization exception.
|
|
30
|
+
def plural_word(singular, plural)
|
|
31
|
+
@plural_of[singular] = plural
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Define a general rule.
|
|
35
|
+
def rule(singular, plural)
|
|
36
|
+
singular_rule(singular, plural)
|
|
37
|
+
plural_rule(singular, plural)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Define a singularization rule.
|
|
41
|
+
def singular_rule(singular, plural)
|
|
42
|
+
@singular_rules << [singular, plural]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Define a plurualization rule.
|
|
46
|
+
def plural_rule(singular, plural)
|
|
47
|
+
@plural_rules << [singular, plural]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Read prepared singularization rules.
|
|
51
|
+
def singularization_rules
|
|
52
|
+
return @singularization_rules if @singularization_rules
|
|
53
|
+
sorted = @singular_rules.sort_by{ |s, p| "#{p}".size }.reverse
|
|
54
|
+
@singularization_rules = sorted.collect do |s, p|
|
|
55
|
+
[ /#{p}$/, "#{s}" ]
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Read prepared pluralization rules.
|
|
60
|
+
def pluralization_rules
|
|
61
|
+
return @pluralization_rules if @pluralization_rules
|
|
62
|
+
sorted = @plural_rules.sort_by{ |s, p| "#{s}".size }.reverse
|
|
63
|
+
@pluralization_rules = sorted.collect do |s, p|
|
|
64
|
+
[ /#{s}$/, "#{p}" ]
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
#
|
|
69
|
+
def plural_of
|
|
70
|
+
@plural_of
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
#
|
|
74
|
+
def singular_of
|
|
75
|
+
@singular_of
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Convert an English word from plurel to singular.
|
|
79
|
+
#
|
|
80
|
+
# "boys".singular #=> boy
|
|
81
|
+
# "tomatoes".singular #=> tomato
|
|
82
|
+
#
|
|
83
|
+
def singular(word)
|
|
84
|
+
if result = singular_of[word]
|
|
85
|
+
return result.dup
|
|
86
|
+
end
|
|
87
|
+
result = word.dup
|
|
88
|
+
singularization_rules.each do |(match, replacement)|
|
|
89
|
+
break if result.gsub!(match, replacement)
|
|
90
|
+
end
|
|
91
|
+
return result
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Alias for #singular (a Railism).
|
|
95
|
+
#
|
|
96
|
+
alias_method(:singularize, :singular)
|
|
97
|
+
|
|
98
|
+
# Convert an English word from singular to plurel.
|
|
99
|
+
#
|
|
100
|
+
# "boy".plural #=> boys
|
|
101
|
+
# "tomato".plural #=> tomatoes
|
|
102
|
+
#
|
|
103
|
+
def plural(word)
|
|
104
|
+
if result = plural_of[word]
|
|
105
|
+
return result.dup
|
|
106
|
+
end
|
|
107
|
+
#return self.dup if /s$/ =~ self # ???
|
|
108
|
+
result = word.dup
|
|
109
|
+
pluralization_rules.each do |(match, replacement)|
|
|
110
|
+
break if result.gsub!(match, replacement)
|
|
111
|
+
end
|
|
112
|
+
return result
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Alias for #plural (a Railism).
|
|
116
|
+
alias_method(:pluralize, :plural)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# One argument means singular and plural are the same.
|
|
120
|
+
|
|
121
|
+
word 'equipment'
|
|
122
|
+
word 'information'
|
|
123
|
+
word 'money'
|
|
124
|
+
word 'species'
|
|
125
|
+
word 'series'
|
|
126
|
+
word 'fish'
|
|
127
|
+
word 'sheep'
|
|
128
|
+
word 'moose'
|
|
129
|
+
word 'hovercraft'
|
|
130
|
+
|
|
131
|
+
# Two arguments defines a singular and plural exception.
|
|
132
|
+
|
|
133
|
+
word 'Swiss' , 'Swiss'
|
|
134
|
+
word 'life' , 'lives'
|
|
135
|
+
word 'wife' , 'wives'
|
|
136
|
+
word 'goose' , 'geese'
|
|
137
|
+
word 'criterion' , 'criteria'
|
|
138
|
+
word 'alias' , 'aliases'
|
|
139
|
+
word 'status' , 'statuses'
|
|
140
|
+
word 'axis' , 'axes'
|
|
141
|
+
word 'crisis' , 'crises'
|
|
142
|
+
word 'testis' , 'testes'
|
|
143
|
+
word 'child' , 'children'
|
|
144
|
+
word 'person' , 'people'
|
|
145
|
+
word 'potato' , 'potatoes'
|
|
146
|
+
word 'tomato' , 'tomatoes'
|
|
147
|
+
word 'buffalo' , 'buffaloes'
|
|
148
|
+
word 'torpedo' , 'torpedoes'
|
|
149
|
+
word 'quiz' , 'quizes'
|
|
150
|
+
word 'matrix' , 'matrices'
|
|
151
|
+
word 'vertex' , 'vetices'
|
|
152
|
+
word 'index' , 'indices'
|
|
153
|
+
word 'ox' , 'oxen'
|
|
154
|
+
word 'mouse' , 'mice'
|
|
155
|
+
word 'louse' , 'lice'
|
|
156
|
+
word 'thesis' , 'theses'
|
|
157
|
+
word 'thief' , 'thieves'
|
|
158
|
+
word 'analysis' , 'analyses'
|
|
159
|
+
|
|
160
|
+
# One-way singularization exception (convert plural to singular).
|
|
161
|
+
|
|
162
|
+
singular_word 'cactus', 'cacti'
|
|
163
|
+
|
|
164
|
+
# General rules.
|
|
165
|
+
|
|
166
|
+
rule 'hive' , 'hives'
|
|
167
|
+
rule 'rf' , 'rves'
|
|
168
|
+
rule 'af' , 'aves'
|
|
169
|
+
rule 'ero' , 'eroes'
|
|
170
|
+
rule 'man' , 'men'
|
|
171
|
+
rule 'ch' , 'ches'
|
|
172
|
+
rule 'sh' , 'shes'
|
|
173
|
+
rule 'ss' , 'sses'
|
|
174
|
+
rule 'ta' , 'tum'
|
|
175
|
+
rule 'ia' , 'ium'
|
|
176
|
+
rule 'ra' , 'rum'
|
|
177
|
+
rule 'ay' , 'ays'
|
|
178
|
+
rule 'ey' , 'eys'
|
|
179
|
+
rule 'oy' , 'oys'
|
|
180
|
+
rule 'uy' , 'uys'
|
|
181
|
+
rule 'y' , 'ies'
|
|
182
|
+
rule 'x' , 'xes'
|
|
183
|
+
rule 'lf' , 'lves'
|
|
184
|
+
rule 'us' , 'uses'
|
|
185
|
+
rule '' , 's'
|
|
186
|
+
|
|
187
|
+
# One-way singular rules.
|
|
188
|
+
|
|
189
|
+
singular_rule 'of' , 'ofs' # proof
|
|
190
|
+
singular_rule 'o' , 'oes' # hero, heroes
|
|
191
|
+
singular_rule 'f' , 'ves'
|
|
192
|
+
|
|
193
|
+
# One-way plural rules.
|
|
194
|
+
|
|
195
|
+
plural_rule 'fe' , 'ves' # safe, wife
|
|
196
|
+
plural_rule 's' , 'ses'
|
|
197
|
+
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
class String
|
|
203
|
+
def singular
|
|
204
|
+
Language::English::Inflect.singular(self)
|
|
205
|
+
end
|
|
206
|
+
alias_method(:singularize, :singular)
|
|
207
|
+
def plural
|
|
208
|
+
Language::English::Inflect.plural(self)
|
|
209
|
+
end
|
|
210
|
+
alias_method(:pluralize, :plural)
|
|
211
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module Merb
|
|
2
|
+
VERSION = '0.9.2' unless defined?(Merb::VERSION)
|
|
3
|
+
|
|
4
|
+
# Merb::RELEASE meanings:
|
|
5
|
+
# 'dev' : unreleased
|
|
6
|
+
# 'pre' : pre-release Gem candidates
|
|
7
|
+
# nil : released
|
|
8
|
+
# You should never check in to trunk with this changed. It should
|
|
9
|
+
# stay 'dev'. Change it to nil in release tags.
|
|
10
|
+
RELEASE = nil unless defined?(Merb::RELEASE)
|
|
11
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
MERB_BIN = File.dirname(__FILE__) + "/../../../bin/merb"
|
|
4
|
+
|
|
5
|
+
describe Merb::Config do
|
|
6
|
+
before do
|
|
7
|
+
ARGV.replace([])
|
|
8
|
+
Merb::Server.should_receive(:start).and_return(nil)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "should load the runner adapter by default" do
|
|
12
|
+
Merb.start
|
|
13
|
+
Merb::Config[:adapter].should == "runner"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "should load mongrel adapter when running `merb`" do
|
|
17
|
+
load(MERB_BIN)
|
|
18
|
+
Merb::Config[:adapter].should == "mongrel"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "should override adapter when running `merb -a other`" do
|
|
22
|
+
ARGV.push *%w[-a other]
|
|
23
|
+
load(MERB_BIN)
|
|
24
|
+
Merb::Config[:adapter].should == "other"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should load irb adapter when running `merb -i`" do
|
|
28
|
+
ARGV << '-i'
|
|
29
|
+
load(MERB_BIN)
|
|
30
|
+
Merb::Config[:adapter].should == "irb"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Merb::Config do
|
|
4
|
+
before do
|
|
5
|
+
Merb::Config.setup
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it "should be able to yield the configuration via #use" do
|
|
9
|
+
res = nil
|
|
10
|
+
Merb::Config.use {|c| res = c}
|
|
11
|
+
res.should == Merb::Config.defaults
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should be able to get a configuration key" do
|
|
15
|
+
Merb::Config[:host].should == "0.0.0.0"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should be able to set a configuration key" do
|
|
19
|
+
Merb::Config[:bar] = "Hello"
|
|
20
|
+
Merb::Config[:bar].should == "Hello"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should be able to #delete a configuration key" do
|
|
24
|
+
Merb::Config[:bar] = "Hello"
|
|
25
|
+
Merb::Config[:bar].should == "Hello"
|
|
26
|
+
Merb::Config.delete(:bar)
|
|
27
|
+
Merb::Config[:bar].should == nil
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "should be able to #fetch a key that does exist" do
|
|
31
|
+
Merb::Config.fetch(:host, "192.168.2.1").should == "0.0.0.0"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should be able to #fetch a key that does exist" do
|
|
35
|
+
Merb::Config.fetch(:bar, "heylo").should == "heylo"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should be able to dump to YAML" do
|
|
39
|
+
Merb::Config.to_yaml.should == Merb::Config.instance_variable_get("@configuration").to_yaml
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "should support -u to set the user to run Merb as" do
|
|
43
|
+
Merb::Config.parse_args(["-u", "tester"])
|
|
44
|
+
Merb::Config[:user].should == "tester"
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should support -G to set the group to run Merb as" do
|
|
48
|
+
Merb::Config.parse_args(["-G", "tester"])
|
|
49
|
+
Merb::Config[:group].should == "tester"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "should support -f to set the filename to run Merb as" do
|
|
53
|
+
Merb::Config.parse_args(["-d"])
|
|
54
|
+
Merb::Config[:daemonize].should == true
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "should support -c to set the number of cluster nodes" do
|
|
58
|
+
Merb::Config.parse_args(["-c", "4"])
|
|
59
|
+
Merb::Config[:cluster].should == "4"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should support -p to set the port number" do
|
|
63
|
+
Merb::Config.parse_args(["-p", "6000"])
|
|
64
|
+
Merb::Config[:port].should == "6000"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "should support -P to set the PIDfile" do
|
|
68
|
+
Merb::Config.parse_args(["-P", "pidfile"])
|
|
69
|
+
Merb::Config[:pid_file].should == "pidfile"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "should support -h to set the hostname" do
|
|
73
|
+
Merb::Config.parse_args(["-h", "hostname"])
|
|
74
|
+
Merb::Config[:host].should == "hostname"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "should support -i to specify loading IRB" do
|
|
78
|
+
Merb::Config.parse_args(["-i"])
|
|
79
|
+
Merb::Config[:adapter].should == "irb"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "should support -l to specify the log level" do
|
|
83
|
+
Merb::Config.parse_args(["-l", "debug"])
|
|
84
|
+
Merb::Config[:log_level].should == :debug
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "should support -L to specify the location of the log file" do
|
|
88
|
+
Merb::Config.parse_args(["-L", "log_file"])
|
|
89
|
+
Merb::Config[:log_file].should == "log_file"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "should support -r to specify a runner" do
|
|
93
|
+
Merb::Config.parse_args(["-r", "foo_runner"])
|
|
94
|
+
Merb::Config[:runner_code].should == "foo_runner"
|
|
95
|
+
Merb::Config[:adapter].should == "runner"
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "should support -K for a graceful kill" do
|
|
99
|
+
Merb::Server.should_receive(:kill).with("all", 1)
|
|
100
|
+
Merb::Config.parse_args(["-K", "all"])
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "should support -k for a hard kill" do
|
|
104
|
+
Merb::Server.should_receive(:kill).with("all", 9)
|
|
105
|
+
Merb::Config.parse_args(["-k", "all"])
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "should support -X off to turn off the mutex" do
|
|
109
|
+
Merb::Config.parse_args(["-X", "off"])
|
|
110
|
+
Merb::Config[:use_mutex].should == false
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "should support -X on to turn off the mutex" do
|
|
114
|
+
Merb::Config.parse_args(["-X", "on"])
|
|
115
|
+
Merb::Config[:use_mutex].should == true
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it "should take Merb.disable into account" do
|
|
119
|
+
Merb::Config[:disabled_components].should == []
|
|
120
|
+
Merb::Config[:disabled_components] << :foo
|
|
121
|
+
Merb.disable(:bar)
|
|
122
|
+
Merb.disable(:buz, :fux)
|
|
123
|
+
Merb::Config[:disabled_components].should == [:foo, :bar, :buz, :fux]
|
|
124
|
+
Merb.disabled?(:foo).should == true
|
|
125
|
+
Merb.disabled?(:foo, :buz).should == true
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "should take Merb.testing? into account" do
|
|
129
|
+
$TESTING.should == true
|
|
130
|
+
Merb::Config[:testing].should be_nil
|
|
131
|
+
Merb.should be_testing
|
|
132
|
+
$TESTING = false
|
|
133
|
+
Merb.should_not be_testing
|
|
134
|
+
Merb::Config[:testing] = true
|
|
135
|
+
Merb.should be_testing
|
|
136
|
+
$TESTING = true; Merb::Config[:testing] = false # reset
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Merb::Config do
|
|
4
|
+
it "should apply environment from the command line option --environment" do
|
|
5
|
+
Merb.start %w( --environment performance_testing )
|
|
6
|
+
Merb.environment.should == "performance_testing"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should apply environment from the command line option -e" do
|
|
10
|
+
Merb.start %w( -e selenium )
|
|
11
|
+
Merb.environment.should == "selenium"
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "..", "spec_helper")
|
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
|
+
require "date"
|
|
3
|
+
require 'bigdecimal'
|
|
4
|
+
|
|
5
|
+
describe Hash, "environmentize_keys!" do
|
|
6
|
+
it "should transform keys to uppercase text" do
|
|
7
|
+
{ :test_1 => 'test', 'test_2' => 'test', 1 => 'test' }.environmentize_keys!.should ==
|
|
8
|
+
{ 'TEST_1' => 'test', 'TEST_2' => 'test', '1' => 'test' }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "should only transform one level of keys" do
|
|
12
|
+
{ :test_1 => { :test2 => 'test'} }.environmentize_keys!.should ==
|
|
13
|
+
{ 'TEST_1' => { :test2 => 'test'} }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
describe Hash, "only" do
|
|
18
|
+
before do
|
|
19
|
+
@hash = { :one => 'ONE', 'two' => 'TWO', 3 => 'THREE' }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should return a hash with only the given key(s)" do
|
|
23
|
+
@hash.only(:one).should == { :one => 'ONE' }
|
|
24
|
+
@hash.only(:one, 3).should == { :one => 'ONE', 3 => 'THREE' }
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe Hash, "except" do
|
|
29
|
+
before do
|
|
30
|
+
@hash = { :one => 'ONE', 'two' => 'TWO', 3 => 'THREE' }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should return a hash without only the given key(s)" do
|
|
34
|
+
@hash.except(:one).should == { 'two' => 'TWO', 3 => 'THREE' }
|
|
35
|
+
@hash.except(:one, 3).should == { 'two' => 'TWO' }
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe Hash, "to_xml_attributes" do
|
|
40
|
+
before do
|
|
41
|
+
@hash = { :one => "ONE", "two" => "TWO" }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "should turn the hash into xml attributes" do
|
|
45
|
+
attrs = @hash.to_xml_attributes
|
|
46
|
+
attrs.should match(/one="ONE"/m)
|
|
47
|
+
attrs.should match(/two="TWO"/m)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe Hash, "from_xml" do
|
|
52
|
+
it "should transform a simple tag with content" do
|
|
53
|
+
xml = "<tag>This is the contents</tag>"
|
|
54
|
+
Hash.from_xml(xml).should == { 'tag' => 'This is the contents' }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "should work with cdata tags" do
|
|
58
|
+
xml = <<-END
|
|
59
|
+
<tag>
|
|
60
|
+
<![CDATA[
|
|
61
|
+
text inside cdata
|
|
62
|
+
]]>
|
|
63
|
+
</tag>
|
|
64
|
+
END
|
|
65
|
+
Hash.from_xml(xml)["tag"].strip.should == "text inside cdata"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "should transform a simple tag with attributes" do
|
|
69
|
+
xml = "<tag attr1='1' attr2='2'></tag>"
|
|
70
|
+
hash = { 'tag' => { 'attr1' => '1', 'attr2' => '2' } }
|
|
71
|
+
Hash.from_xml(xml).should == hash
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "should transform repeating siblings into an array" do
|
|
75
|
+
xml =<<-XML
|
|
76
|
+
<opt>
|
|
77
|
+
<user login="grep" fullname="Gary R Epstein" />
|
|
78
|
+
<user login="stty" fullname="Simon T Tyson" />
|
|
79
|
+
</opt>
|
|
80
|
+
XML
|
|
81
|
+
|
|
82
|
+
Hash.from_xml(xml)['opt']['user'].should be_an_instance_of(Array)
|
|
83
|
+
|
|
84
|
+
hash = {
|
|
85
|
+
'opt' => {
|
|
86
|
+
'user' => [{
|
|
87
|
+
'login' => 'grep',
|
|
88
|
+
'fullname' => 'Gary R Epstein'
|
|
89
|
+
},{
|
|
90
|
+
'login' => 'stty',
|
|
91
|
+
'fullname' => 'Simon T Tyson'
|
|
92
|
+
}]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
Hash.from_xml(xml).should == hash
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "should not transform non-repeating siblings into an array" do
|
|
100
|
+
xml =<<-XML
|
|
101
|
+
<opt>
|
|
102
|
+
<user login="grep" fullname="Gary R Epstein" />
|
|
103
|
+
</opt>
|
|
104
|
+
XML
|
|
105
|
+
|
|
106
|
+
Hash.from_xml(xml)['opt']['user'].should be_an_instance_of(Hash)
|
|
107
|
+
|
|
108
|
+
hash = {
|
|
109
|
+
'opt' => {
|
|
110
|
+
'user' => {
|
|
111
|
+
'login' => 'grep',
|
|
112
|
+
'fullname' => 'Gary R Epstein'
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
Hash.from_xml(xml).should == hash
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it "should typecast an integer" do
|
|
121
|
+
xml = "<tag type='integer'>10</tag>"
|
|
122
|
+
Hash.from_xml(xml)['tag'].should == 10
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it "should typecast a true boolean" do
|
|
126
|
+
xml = "<tag type='boolean'>true</tag>"
|
|
127
|
+
Hash.from_xml(xml)['tag'].should be_true
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it "should typecast a false boolean" do
|
|
131
|
+
["false"].each do |w|
|
|
132
|
+
Hash.from_xml("<tag type='boolean'>#{w}</tag>")['tag'].should be_false
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it "should typecast a datetime" do
|
|
137
|
+
xml = "<tag type='datetime'>2007-12-31 10:32</tag>"
|
|
138
|
+
Hash.from_xml(xml)['tag'].should == Time.parse( '2007-12-31 10:32' ).utc
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
it "should typecast a date" do
|
|
142
|
+
xml = "<tag type='date'>2007-12-31</tag>"
|
|
143
|
+
Hash.from_xml(xml)['tag'].should == Date.parse('2007-12-31')
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it "should unescape html entities" do
|
|
147
|
+
values = {
|
|
148
|
+
"<" => "<",
|
|
149
|
+
">" => ">",
|
|
150
|
+
'"' => """,
|
|
151
|
+
"'" => "'",
|
|
152
|
+
"&" => "&"
|
|
153
|
+
}
|
|
154
|
+
values.each do |k,v|
|
|
155
|
+
xml = "<tag>Some content #{v}</tag>"
|
|
156
|
+
Hash.from_xml(xml)['tag'].should match(Regexp.new(k))
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
it "should undasherize keys as tags" do
|
|
161
|
+
xml = "<tag-1>Stuff</tag-1>"
|
|
162
|
+
Hash.from_xml(xml).keys.should include( 'tag_1' )
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
it "should undasherize keys as attributes" do
|
|
166
|
+
xml = "<tag1 attr-1='1'></tag1>"
|
|
167
|
+
Hash.from_xml(xml)['tag1'].keys.should include( 'attr_1')
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it "should undasherize keys as tags and attributes" do
|
|
171
|
+
xml = "<tag-1 attr-1='1'></tag-1>"
|
|
172
|
+
Hash.from_xml(xml).keys.should include( 'tag_1' )
|
|
173
|
+
Hash.from_xml(xml)['tag_1'].keys.should include( 'attr_1')
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
it "should render nested content correctly" do
|
|
177
|
+
xml = "<root><tag1>Tag1 Content <em><strong>This is strong</strong></em></tag1></root>"
|
|
178
|
+
Hash.from_xml(xml)['root']['tag1'].should == "Tag1 Content <em><strong>This is strong</strong></em>"
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
it "should render nested content with split text nodes correctly" do
|
|
182
|
+
xml = "<root>Tag1 Content<em>Stuff</em> Hi There</root>"
|
|
183
|
+
Hash.from_xml(xml)['root'].should == "Tag1 Content<em>Stuff</em> Hi There"
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it "should ignore attributes when a child is a text node" do
|
|
187
|
+
xml = "<root attr1='1'>Stuff</root>"
|
|
188
|
+
Hash.from_xml(xml).should == { "root" => "Stuff" }
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
it "should ignore attributes when any child is a text node" do
|
|
192
|
+
xml = "<root attr1='1'>Stuff <em>in italics</em></root>"
|
|
193
|
+
Hash.from_xml(xml).should == { "root" => "Stuff <em>in italics</em>" }
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it "should correctly transform multiple children" do
|
|
197
|
+
xml = <<-XML
|
|
198
|
+
<user gender='m'>
|
|
199
|
+
<age type='integer'>35</age>
|
|
200
|
+
<name>Home Simpson</name>
|
|
201
|
+
<dob type='date'>1988-01-01</dob>
|
|
202
|
+
<joined-at type='datetime'>2000-04-28 23:01</joined-at>
|
|
203
|
+
<is-cool type='boolean'>true</is-cool>
|
|
204
|
+
</user>
|
|
205
|
+
XML
|
|
206
|
+
|
|
207
|
+
hash = {
|
|
208
|
+
"user" => {
|
|
209
|
+
"gender" => "m",
|
|
210
|
+
"age" => 35,
|
|
211
|
+
"name" => "Home Simpson",
|
|
212
|
+
"dob" => Date.parse('1988-01-01'),
|
|
213
|
+
"joined_at" => Time.parse("2000-04-28 23:01"),
|
|
214
|
+
"is_cool" => true
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
Hash.from_xml(xml).should == hash
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
it "should properly handle nil values (ActiveSupport Compatible)" do
|
|
222
|
+
topic_xml = <<-EOT
|
|
223
|
+
<topic>
|
|
224
|
+
<title></title>
|
|
225
|
+
<id type="integer"></id>
|
|
226
|
+
<approved type="boolean"></approved>
|
|
227
|
+
<written-on type="date"></written-on>
|
|
228
|
+
<viewed-at type="datetime"></viewed-at>
|
|
229
|
+
<content type="yaml"></content>
|
|
230
|
+
<parent-id></parent-id>
|
|
231
|
+
</topic>
|
|
232
|
+
EOT
|
|
233
|
+
|
|
234
|
+
expected_topic_hash = {
|
|
235
|
+
'title' => nil,
|
|
236
|
+
'id' => nil,
|
|
237
|
+
'approved' => nil,
|
|
238
|
+
'written_on' => nil,
|
|
239
|
+
'viewed_at' => nil,
|
|
240
|
+
'content' => nil,
|
|
241
|
+
'parent_id' => nil
|
|
242
|
+
}
|
|
243
|
+
Hash.from_xml(topic_xml)["topic"].should == expected_topic_hash
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
it "should handle a single record from xml (ActiveSupport Compatible)" do
|
|
247
|
+
topic_xml = <<-EOT
|
|
248
|
+
<topic>
|
|
249
|
+
<title>The First Topic</title>
|
|
250
|
+
<author-name>David</author-name>
|
|
251
|
+
<id type="integer">1</id>
|
|
252
|
+
<approved type="boolean"> true </approved>
|
|
253
|
+
<replies-count type="integer">0</replies-count>
|
|
254
|
+
<replies-close-in type="integer">2592000000</replies-close-in>
|
|
255
|
+
<written-on type="date">2003-07-16</written-on>
|
|
256
|
+
<viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
|
|
257
|
+
<content type="yaml">--- \n1: should be an integer\n:message: Have a nice day\narray: \n- should-have-dashes: true\n should_have_underscores: true\n</content>
|
|
258
|
+
<author-email-address>david@loudthinking.com</author-email-address>
|
|
259
|
+
<parent-id></parent-id>
|
|
260
|
+
<ad-revenue type="decimal">1.5</ad-revenue>
|
|
261
|
+
<optimum-viewing-angle type="float">135</optimum-viewing-angle>
|
|
262
|
+
<resident type="symbol">yes</resident>
|
|
263
|
+
</topic>
|
|
264
|
+
EOT
|
|
265
|
+
|
|
266
|
+
expected_topic_hash = {
|
|
267
|
+
'title' => "The First Topic",
|
|
268
|
+
'author_name' => "David",
|
|
269
|
+
'id' => 1,
|
|
270
|
+
'approved' => true,
|
|
271
|
+
'replies_count' => 0,
|
|
272
|
+
'replies_close_in' => 2592000000,
|
|
273
|
+
'written_on' => Date.new(2003, 7, 16),
|
|
274
|
+
'viewed_at' => Time.utc(2003, 7, 16, 9, 28),
|
|
275
|
+
# Changed this line where the key is :message. The yaml specifies this as a symbol, and who am I to change what you specify
|
|
276
|
+
# The line in ActiveSupport is
|
|
277
|
+
# 'content' => { 'message' => "Have a nice day", 1 => "should be an integer", "array" => [{ "should-have-dashes" => true, "should_have_underscores" => true }] },
|
|
278
|
+
'content' => { :message => "Have a nice day", 1 => "should be an integer", "array" => [{ "should-have-dashes" => true, "should_have_underscores" => true }] },
|
|
279
|
+
'author_email_address' => "david@loudthinking.com",
|
|
280
|
+
'parent_id' => nil,
|
|
281
|
+
'ad_revenue' => BigDecimal("1.50"),
|
|
282
|
+
'optimum_viewing_angle' => 135.0,
|
|
283
|
+
'resident' => :yes
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
Hash.from_xml(topic_xml)["topic"].each do |k,v|
|
|
287
|
+
v.should == expected_topic_hash[k]
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
it "should handle multiple records (ActiveSupport Compatible)" do
|
|
292
|
+
topics_xml = <<-EOT
|
|
293
|
+
<topics type="array">
|
|
294
|
+
<topic>
|
|
295
|
+
<title>The First Topic</title>
|
|
296
|
+
<author-name>David</author-name>
|
|
297
|
+
<id type="integer">1</id>
|
|
298
|
+
<approved type="boolean">false</approved>
|
|
299
|
+
<replies-count type="integer">0</replies-count>
|
|
300
|
+
<replies-close-in type="integer">2592000000</replies-close-in>
|
|
301
|
+
<written-on type="date">2003-07-16</written-on>
|
|
302
|
+
<viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
|
|
303
|
+
<content>Have a nice day</content>
|
|
304
|
+
<author-email-address>david@loudthinking.com</author-email-address>
|
|
305
|
+
<parent-id nil="true"></parent-id>
|
|
306
|
+
</topic>
|
|
307
|
+
<topic>
|
|
308
|
+
<title>The Second Topic</title>
|
|
309
|
+
<author-name>Jason</author-name>
|
|
310
|
+
<id type="integer">1</id>
|
|
311
|
+
<approved type="boolean">false</approved>
|
|
312
|
+
<replies-count type="integer">0</replies-count>
|
|
313
|
+
<replies-close-in type="integer">2592000000</replies-close-in>
|
|
314
|
+
<written-on type="date">2003-07-16</written-on>
|
|
315
|
+
<viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
|
|
316
|
+
<content>Have a nice day</content>
|
|
317
|
+
<author-email-address>david@loudthinking.com</author-email-address>
|
|
318
|
+
<parent-id></parent-id>
|
|
319
|
+
</topic>
|
|
320
|
+
</topics>
|
|
321
|
+
EOT
|
|
322
|
+
|
|
323
|
+
expected_topic_hash = {
|
|
324
|
+
'title' => "The First Topic",
|
|
325
|
+
'author_name' => "David",
|
|
326
|
+
'id' => 1,
|
|
327
|
+
'approved' => false,
|
|
328
|
+
'replies_count' => 0,
|
|
329
|
+
'replies_close_in' => 2592000000,
|
|
330
|
+
'written_on' => Date.new(2003, 7, 16),
|
|
331
|
+
'viewed_at' => Time.utc(2003, 7, 16, 9, 28),
|
|
332
|
+
'content' => "Have a nice day",
|
|
333
|
+
'author_email_address' => "david@loudthinking.com",
|
|
334
|
+
'parent_id' => nil
|
|
335
|
+
}
|
|
336
|
+
# puts Hash.from_xml(topics_xml)['topics'].first.inspect
|
|
337
|
+
Hash.from_xml(topics_xml)["topics"].first.each do |k,v|
|
|
338
|
+
v.should == expected_topic_hash[k]
|
|
339
|
+
end
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
it "should handle a single record from_xml with attributes other than type (ActiveSupport Compatible)" do
|
|
343
|
+
topic_xml = <<-EOT
|
|
344
|
+
<rsp stat="ok">
|
|
345
|
+
<photos page="1" pages="1" perpage="100" total="16">
|
|
346
|
+
<photo id="175756086" owner="55569174@N00" secret="0279bf37a1" server="76" title="Colored Pencil PhotoBooth Fun" ispublic="1" isfriend="0" isfamily="0"/>
|
|
347
|
+
</photos>
|
|
348
|
+
</rsp>
|
|
349
|
+
EOT
|
|
350
|
+
|
|
351
|
+
expected_topic_hash = {
|
|
352
|
+
'id' => "175756086",
|
|
353
|
+
'owner' => "55569174@N00",
|
|
354
|
+
'secret' => "0279bf37a1",
|
|
355
|
+
'server' => "76",
|
|
356
|
+
'title' => "Colored Pencil PhotoBooth Fun",
|
|
357
|
+
'ispublic' => "1",
|
|
358
|
+
'isfriend' => "0",
|
|
359
|
+
'isfamily' => "0",
|
|
360
|
+
}
|
|
361
|
+
Hash.from_xml(topic_xml)["rsp"]["photos"]["photo"].each do |k,v|
|
|
362
|
+
v.should == expected_topic_hash[k]
|
|
363
|
+
end
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
it "should handle an emtpy array (ActiveSupport Compatible)" do
|
|
367
|
+
blog_xml = <<-XML
|
|
368
|
+
<blog>
|
|
369
|
+
<posts type="array"></posts>
|
|
370
|
+
</blog>
|
|
371
|
+
XML
|
|
372
|
+
expected_blog_hash = {"blog" => {"posts" => []}}
|
|
373
|
+
Hash.from_xml(blog_xml).should == expected_blog_hash
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
it "should handle empty array with whitespace from xml (ActiveSupport Compatible)" do
|
|
377
|
+
blog_xml = <<-XML
|
|
378
|
+
<blog>
|
|
379
|
+
<posts type="array">
|
|
380
|
+
</posts>
|
|
381
|
+
</blog>
|
|
382
|
+
XML
|
|
383
|
+
expected_blog_hash = {"blog" => {"posts" => []}}
|
|
384
|
+
Hash.from_xml(blog_xml).should == expected_blog_hash
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
it "should handle array with one entry from_xml (ActiveSupport Compatible)" do
|
|
388
|
+
blog_xml = <<-XML
|
|
389
|
+
<blog>
|
|
390
|
+
<posts type="array">
|
|
391
|
+
<post>a post</post>
|
|
392
|
+
</posts>
|
|
393
|
+
</blog>
|
|
394
|
+
XML
|
|
395
|
+
expected_blog_hash = {"blog" => {"posts" => ["a post"]}}
|
|
396
|
+
Hash.from_xml(blog_xml).should == expected_blog_hash
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
it "should handle array with multiple entries from xml (ActiveSupport Compatible)" do
|
|
400
|
+
blog_xml = <<-XML
|
|
401
|
+
<blog>
|
|
402
|
+
<posts type="array">
|
|
403
|
+
<post>a post</post>
|
|
404
|
+
<post>another post</post>
|
|
405
|
+
</posts>
|
|
406
|
+
</blog>
|
|
407
|
+
XML
|
|
408
|
+
expected_blog_hash = {"blog" => {"posts" => ["a post", "another post"]}}
|
|
409
|
+
Hash.from_xml(blog_xml).should == expected_blog_hash
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
it "should handle file types (ActiveSupport Compatible)" do
|
|
413
|
+
blog_xml = <<-XML
|
|
414
|
+
<blog>
|
|
415
|
+
<logo type="file" name="logo.png" content_type="image/png">
|
|
416
|
+
</logo>
|
|
417
|
+
</blog>
|
|
418
|
+
XML
|
|
419
|
+
hash = Hash.from_xml(blog_xml)
|
|
420
|
+
hash.should have_key('blog')
|
|
421
|
+
hash['blog'].should have_key('logo')
|
|
422
|
+
|
|
423
|
+
file = hash['blog']['logo']
|
|
424
|
+
file.original_filename.should == 'logo.png'
|
|
425
|
+
file.content_type.should == 'image/png'
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
it "should handle file from xml with defaults (ActiveSupport Compatible)" do
|
|
429
|
+
blog_xml = <<-XML
|
|
430
|
+
<blog>
|
|
431
|
+
<logo type="file">
|
|
432
|
+
</logo>
|
|
433
|
+
</blog>
|
|
434
|
+
XML
|
|
435
|
+
file = Hash.from_xml(blog_xml)['blog']['logo']
|
|
436
|
+
file.original_filename.should == 'untitled'
|
|
437
|
+
file.content_type.should == 'application/octet-stream'
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
it "should handle xsd like types from xml (ActiveSupport Compatible)" do
|
|
441
|
+
bacon_xml = <<-EOT
|
|
442
|
+
<bacon>
|
|
443
|
+
<weight type="double">0.5</weight>
|
|
444
|
+
<price type="decimal">12.50</price>
|
|
445
|
+
<chunky type="boolean"> 1 </chunky>
|
|
446
|
+
<expires-at type="dateTime">2007-12-25T12:34:56+0000</expires-at>
|
|
447
|
+
<notes type="string"></notes>
|
|
448
|
+
<illustration type="base64Binary">YmFiZS5wbmc=</illustration>
|
|
449
|
+
</bacon>
|
|
450
|
+
EOT
|
|
451
|
+
|
|
452
|
+
expected_bacon_hash = {
|
|
453
|
+
'weight' => 0.5,
|
|
454
|
+
'chunky' => true,
|
|
455
|
+
'price' => BigDecimal("12.50"),
|
|
456
|
+
'expires_at' => Time.utc(2007,12,25,12,34,56),
|
|
457
|
+
'notes' => "",
|
|
458
|
+
'illustration' => "babe.png"
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
Hash.from_xml(bacon_xml)["bacon"].should == expected_bacon_hash
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
it "should let type trickle through when unknown (ActiveSupport Compatible)" do
|
|
465
|
+
product_xml = <<-EOT
|
|
466
|
+
<product>
|
|
467
|
+
<weight type="double">0.5</weight>
|
|
468
|
+
<image type="ProductImage"><filename>image.gif</filename></image>
|
|
469
|
+
|
|
470
|
+
</product>
|
|
471
|
+
EOT
|
|
472
|
+
|
|
473
|
+
expected_product_hash = {
|
|
474
|
+
'weight' => 0.5,
|
|
475
|
+
'image' => {'type' => 'ProductImage', 'filename' => 'image.gif' },
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
Hash.from_xml(product_xml)["product"].should == expected_product_hash
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
it "should handle unescaping from xml (ActiveResource Compatible)" do
|
|
482
|
+
xml_string = '<person><bare-string>First & Last Name</bare-string><pre-escaped-string>First &amp; Last Name</pre-escaped-string></person>'
|
|
483
|
+
expected_hash = {
|
|
484
|
+
'bare_string' => 'First & Last Name',
|
|
485
|
+
'pre_escaped_string' => 'First & Last Name'
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
Hash.from_xml(xml_string)['person'].should == expected_hash
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
describe Hash, 'to_params' do
|
|
494
|
+
before do
|
|
495
|
+
@hash = { :name => 'Bob', :address => { :street => '111 Ruby Ave.', :city => 'Ruby Central', :phones => ['111-111-1111', '222-222-2222'] } }
|
|
496
|
+
end
|
|
497
|
+
|
|
498
|
+
it 'should convert correctly into query parameters' do
|
|
499
|
+
@hash.to_params.split('&').sort.should ==
|
|
500
|
+
'name=Bob&address[city]=Ruby Central&address[phones]=111-111-1111222-222-2222&address[street]=111 Ruby Ave.'.split('&').sort
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
it 'should not leave a trailing &' do
|
|
504
|
+
@hash.to_params.should_not match(/&$/)
|
|
505
|
+
end
|
|
506
|
+
end
|