middleman 2.0.4 → 2.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (172) hide show
  1. data/CHANGELOG +8 -0
  2. data/lib/middleman.rb +7 -1
  3. data/lib/middleman/vendor/padrino-core-0.10.0/.document +5 -0
  4. data/lib/middleman/vendor/padrino-core-0.10.0/.gitignore +22 -0
  5. data/lib/middleman/vendor/padrino-core-0.10.0/LICENSE +20 -0
  6. data/lib/middleman/vendor/padrino-core-0.10.0/README.rdoc +294 -0
  7. data/lib/middleman/vendor/padrino-core-0.10.0/Rakefile +5 -0
  8. data/lib/middleman/vendor/padrino-core-0.10.0/bin/padrino +9 -0
  9. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core.rb +119 -0
  10. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/application.rb +259 -0
  11. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/application/rendering.rb +228 -0
  12. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/application/routing.rb +821 -0
  13. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/application/showexceptions.rb +18 -0
  14. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/caller.rb +45 -0
  15. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/cli/adapter.rb +24 -0
  16. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/cli/base.rb +152 -0
  17. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/cli/console.rb +20 -0
  18. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/cli/rake.rb +24 -0
  19. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/cli/rake_tasks.rb +59 -0
  20. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/command.rb +27 -0
  21. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/images/404.png +0 -0
  22. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/images/500.png +0 -0
  23. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/loader.rb +182 -0
  24. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/cz.yml +30 -0
  25. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/da.yml +30 -0
  26. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/de.yml +30 -0
  27. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/en.yml +30 -0
  28. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/es.yml +30 -0
  29. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/fr.yml +30 -0
  30. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/hu.yml +30 -0
  31. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/it.yml +37 -0
  32. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/ja.yml +30 -0
  33. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/nl.yml +30 -0
  34. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/no.yml +31 -0
  35. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/pl.yml +30 -0
  36. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/pt_br.yml +37 -0
  37. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/ru.yml +30 -0
  38. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/tr.yml +30 -0
  39. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/uk.yml +30 -0
  40. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/zh_cn.yml +30 -0
  41. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/locale/zh_tw.yml +30 -0
  42. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/logger.rb +344 -0
  43. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/mounter.rb +192 -0
  44. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/reloader.rb +247 -0
  45. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/router.rb +79 -0
  46. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/server.rb +70 -0
  47. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/support_lite.rb +135 -0
  48. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/tasks.rb +23 -0
  49. data/lib/middleman/vendor/padrino-core-0.10.0/lib/padrino-core/version.rb +15 -0
  50. data/lib/middleman/vendor/padrino-core-0.10.0/padrino-core.gemspec +38 -0
  51. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/apps/.components +6 -0
  52. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/apps/.gitignore +7 -0
  53. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/apps/complex.rb +27 -0
  54. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/apps/simple.rb +33 -0
  55. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/dependencies/a.rb +9 -0
  56. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/dependencies/b.rb +4 -0
  57. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/dependencies/c.rb +1 -0
  58. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/dependencies/circular/e.rb +13 -0
  59. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/dependencies/circular/f.rb +2 -0
  60. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/dependencies/circular/g.rb +2 -0
  61. data/lib/middleman/vendor/padrino-core-0.10.0/test/fixtures/dependencies/d.rb +4 -0
  62. data/lib/middleman/vendor/padrino-core-0.10.0/test/helper.rb +101 -0
  63. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_application.rb +83 -0
  64. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_core.rb +79 -0
  65. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_dependencies.rb +44 -0
  66. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_filters.rb +266 -0
  67. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_logger.rb +91 -0
  68. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_mounter.rb +176 -0
  69. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_reloader_complex.rb +66 -0
  70. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_reloader_simple.rb +97 -0
  71. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_rendering.rb +437 -0
  72. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_router.rb +146 -0
  73. data/lib/middleman/vendor/padrino-core-0.10.0/test/test_routing.rb +1491 -0
  74. data/lib/middleman/vendor/padrino-helpers-0.10.0/.document +5 -0
  75. data/lib/middleman/vendor/padrino-helpers-0.10.0/.gitignore +21 -0
  76. data/lib/middleman/vendor/padrino-helpers-0.10.0/LICENSE +20 -0
  77. data/lib/middleman/vendor/padrino-helpers-0.10.0/README.rdoc +239 -0
  78. data/lib/middleman/vendor/padrino-helpers-0.10.0/Rakefile +5 -0
  79. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers.rb +51 -0
  80. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/asset_tag_helpers.rb +288 -0
  81. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/form_builder/abstract_form_builder.rb +220 -0
  82. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/form_builder/standard_form_builder.rb +43 -0
  83. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/form_helpers.rb +446 -0
  84. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/format_helpers.rb +260 -0
  85. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/cz.yml +103 -0
  86. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/da.yml +91 -0
  87. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/de.yml +78 -0
  88. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/en.yml +103 -0
  89. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/es.yml +103 -0
  90. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/fr.yml +79 -0
  91. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/hu.yml +103 -0
  92. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/it.yml +85 -0
  93. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/ja.yml +103 -0
  94. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/nl.yml +78 -0
  95. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/no.yml +91 -0
  96. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/pl.yml +95 -0
  97. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/pt_br.yml +103 -0
  98. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/ru.yml +103 -0
  99. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/tr.yml +103 -0
  100. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/uk.yml +103 -0
  101. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/zh_cn.yml +103 -0
  102. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/locale/zh_tw.yml +103 -0
  103. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/number_helpers.rb +273 -0
  104. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/output_helpers.rb +128 -0
  105. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/output_helpers/abstract_handler.rb +103 -0
  106. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/output_helpers/erb_handler.rb +79 -0
  107. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/output_helpers/haml_handler.rb +64 -0
  108. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/output_helpers/slim_handler.rb +82 -0
  109. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/render_helpers.rb +40 -0
  110. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/tag_helpers.rb +59 -0
  111. data/lib/middleman/vendor/padrino-helpers-0.10.0/lib/padrino-helpers/translation_helpers.rb +21 -0
  112. data/lib/middleman/vendor/padrino-helpers-0.10.0/padrino-helpers.gemspec +27 -0
  113. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/app.rb +73 -0
  114. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/capture_concat.erb +14 -0
  115. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/capture_concat.haml +12 -0
  116. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/capture_concat.slim +13 -0
  117. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/content_for.erb +11 -0
  118. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/content_for.haml +9 -0
  119. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/content_for.slim +9 -0
  120. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/content_tag.erb +11 -0
  121. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/content_tag.haml +9 -0
  122. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/content_tag.slim +9 -0
  123. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/current_engine.erb +5 -0
  124. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/current_engine.haml +5 -0
  125. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/current_engine.slim +5 -0
  126. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/fields_for.erb +20 -0
  127. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/fields_for.haml +15 -0
  128. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/fields_for.slim +15 -0
  129. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/form_for.erb +56 -0
  130. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/form_for.haml +47 -0
  131. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/form_for.slim +47 -0
  132. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/form_tag.erb +56 -0
  133. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/form_tag.haml +45 -0
  134. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/form_tag.slim +45 -0
  135. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/link_to.erb +5 -0
  136. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/link_to.haml +4 -0
  137. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/link_to.slim +4 -0
  138. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/mail_to.erb +3 -0
  139. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/mail_to.haml +3 -0
  140. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/mail_to.slim +3 -0
  141. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/meta_tag.erb +3 -0
  142. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/meta_tag.haml +3 -0
  143. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/meta_tag.slim +3 -0
  144. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/partials/_erb.erb +1 -0
  145. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/partials/_haml.haml +1 -0
  146. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/partials/_slim.slim +1 -0
  147. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/simple_partial.erb +1 -0
  148. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/simple_partial.haml +1 -0
  149. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/markup_app/views/simple_partial.slim +1 -0
  150. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/app.rb +45 -0
  151. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/current_engine.haml +5 -0
  152. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/current_engines/_erb.erb +1 -0
  153. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/current_engines/_haml.haml +1 -0
  154. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/current_engines/_slim.slim +1 -0
  155. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/erb/test.erb +1 -0
  156. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/explicit_engine.haml +5 -0
  157. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/haml/test.haml +1 -0
  158. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/template/_user.haml +7 -0
  159. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/template/haml_template.haml +1 -0
  160. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/fixtures/render_app/views/template/some_template.haml +2 -0
  161. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/helper.rb +78 -0
  162. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/test_asset_tag_helpers.rb +320 -0
  163. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/test_form_builder.rb +998 -0
  164. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/test_form_helpers.rb +645 -0
  165. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/test_format_helpers.rb +227 -0
  166. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/test_number_helpers.rb +136 -0
  167. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/test_output_helpers.rb +133 -0
  168. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/test_render_helpers.rb +69 -0
  169. data/lib/middleman/vendor/padrino-helpers-0.10.0/test/test_tag_helpers.rb +100 -0
  170. data/lib/middleman/version.rb +1 -1
  171. data/middleman.gemspec +6 -2
  172. metadata +218 -67
@@ -0,0 +1,192 @@
1
+ module Padrino
2
+ ##
3
+ # Represents a particular mounted padrino application
4
+ # Stores the name of the application (app folder name) and url mount path
5
+ #
6
+ # ==== Examples
7
+ #
8
+ # Mounter.new("blog_app", :app_class => "Blog").to("/blog")
9
+ # Mounter.new("blog_app", :app_file => "/path/to/blog/app.rb").to("/blog")
10
+ #
11
+ class Mounter
12
+ class MounterException < RuntimeError #:nodoc:
13
+ end
14
+
15
+ attr_accessor :name, :uri_root, :app_file, :app_class, :app_root, :app_obj, :app_host
16
+
17
+ def initialize(name, options={})
18
+ @name = name.to_s
19
+ @app_class = options[:app_class] || @name.camelize
20
+ @app_file = options[:app_file] || locate_app_file
21
+ @app_obj = options[:app_obj] || app_constant || locate_app_object
22
+ ensure_app_file! || ensure_app_object!
23
+ @app_root = options[:app_root] || File.dirname(@app_file)
24
+ @uri_root = "/"
25
+ Padrino::Reloader.exclude_constants << @app_class
26
+ end
27
+
28
+ ##
29
+ # Registers the mounted application onto Padrino
30
+ #
31
+ # ==== Examples
32
+ #
33
+ # Mounter.new("blog_app").to("/blog")
34
+ #
35
+ def to(mount_url)
36
+ @uri_root = mount_url
37
+ Padrino.insert_mounted_app(self)
38
+ self
39
+ end
40
+
41
+ ##
42
+ # Registers the mounted application onto Padrino for the given host
43
+ #
44
+ # ==== Examples
45
+ #
46
+ # Mounter.new("blog_app").to("/blog").host("blog.padrino.org")
47
+ # Mounter.new("blog_app").host("blog.padrino.org")
48
+ # Mounter.new("catch_all").host(/.*\.padrino.org/)
49
+ #
50
+ def host(mount_host)
51
+ @app_host = mount_host
52
+ Padrino.insert_mounted_app(self)
53
+ self
54
+ end
55
+
56
+ ##
57
+ # Maps Padrino application onto a Padrino::Router
58
+ # For use in constructing a Rack application
59
+ #
60
+ # @app.map_onto(router)
61
+ #
62
+ def map_onto(router)
63
+ app_data, app_obj = self, @app_obj
64
+ app_obj.set :uri_root, app_data.uri_root
65
+ app_obj.set :app_name, app_data.name
66
+ app_obj.set :app_file, app_data.app_file unless ::File.exist?(app_obj.app_file)
67
+ app_obj.set :root, app_data.app_root unless app_data.app_root.blank?
68
+ app_obj.set :public, Padrino.root('public', app_data.uri_root) unless File.exists?(app_obj.public)
69
+ app_obj.set :static, File.exist?(app_obj.public) if app_obj.nil?
70
+ app_obj.setup_application! # We need to initialize here the app.
71
+ router.map(:to => app_obj, :path => app_data.uri_root, :host => app_data.app_host)
72
+ end
73
+
74
+ ###
75
+ # Returns the route objects for the mounted application
76
+ #
77
+ def routes
78
+ app_obj.routes
79
+ end
80
+
81
+ ###
82
+ # Returns the basic route information for each named route
83
+ #
84
+ #
85
+ def named_routes
86
+ app_obj.routes.map { |route|
87
+ name_array = "(#{route.named.to_s.split("_").map { |piece| %Q[:#{piece}] }.join(", ")})"
88
+ request_method = route.conditions[:request_method][0]
89
+ full_path = File.join(uri_root, route.original_path)
90
+ next if route.named.blank? || request_method == 'HEAD'
91
+ OpenStruct.new(:verb => request_method, :identifier => route.named, :name => name_array, :path => full_path)
92
+ }.compact
93
+ end
94
+
95
+ ##
96
+ # Makes two Mounters equal if they have the same name and uri_root
97
+ #
98
+ def ==(other)
99
+ other.is_a?(Mounter) && self.app_class == other.app_class && self.uri_root == other.uri_root
100
+ end
101
+
102
+ ##
103
+ # Returns the class object for the app if defined, nil otherwise
104
+ #
105
+ def app_constant
106
+ klass = Object
107
+ for piece in app_class.split("::")
108
+ piece = piece.to_sym
109
+ if klass.const_defined?(piece)
110
+ klass = klass.const_get(piece)
111
+ else
112
+ return
113
+ end
114
+ end
115
+ klass
116
+ end
117
+
118
+ protected
119
+ ##
120
+ # Locates and requires the file to load the app constant
121
+ #
122
+ def locate_app_object
123
+ @_app_object ||= begin
124
+ ensure_app_file!
125
+ Padrino.require_dependencies(app_file)
126
+ app_constant
127
+ end
128
+ end
129
+
130
+ ##
131
+ # Returns the determined location of the mounted application main file
132
+ #
133
+ def locate_app_file
134
+ candidates = []
135
+ candidates << app_constant.app_file if app_constant.respond_to?(:app_file) && File.exist?(app_constant.app_file.to_s)
136
+ candidates << Padrino.first_caller if File.identical?(Padrino.first_caller.to_s, Padrino.called_from.to_s)
137
+ candidates << Padrino.mounted_root(name.downcase, "app.rb")
138
+ candidates << Padrino.root("app", "app.rb")
139
+ candidates.find { |candidate| File.exist?(candidate) }
140
+ end
141
+
142
+ ###
143
+ # Raises an exception unless app_file is located properly
144
+ #
145
+ def ensure_app_file!
146
+ message = "Unable to locate source file for app '#{app_class}', try with :app_file => '/path/app.rb'"
147
+ raise MounterException, message unless @app_file
148
+ end
149
+
150
+ ###
151
+ # Raises an exception unless app_obj is defined properly
152
+ #
153
+ def ensure_app_object!
154
+ message = "Unable to locate app for '#{app_class}', try with :app_class => 'MyAppClass'"
155
+ raise MounterException, message unless @app_obj
156
+ end
157
+ end
158
+
159
+ class << self
160
+ attr_writer :mounted_root # Set root directory where padrino searches mounted apps
161
+
162
+ ##
163
+ # Returns the root to the mounted apps base directory
164
+ #
165
+ def mounted_root(*args)
166
+ Padrino.root(@mounted_root ||= "", *args)
167
+ end
168
+
169
+ ##
170
+ # Returns the mounted padrino applications (MountedApp objects)
171
+ #
172
+ def mounted_apps
173
+ @mounted_apps ||= []
174
+ end
175
+
176
+ ##
177
+ # Inserts a Mounter object into the mounted applications (avoids duplicates)
178
+ #
179
+ def insert_mounted_app(mounter)
180
+ Padrino.mounted_apps.push(mounter) unless Padrino.mounted_apps.include?(mounter)
181
+ end
182
+
183
+ ##
184
+ # Mounts a new sub-application onto Padrino project
185
+ #
186
+ # Padrino.mount("blog_app").to("/blog")
187
+ #
188
+ def mount(name, options={})
189
+ Mounter.new(name, options)
190
+ end
191
+ end # Mounter
192
+ end # Padrino
@@ -0,0 +1,247 @@
1
+ require 'pathname'
2
+
3
+ module Padrino
4
+ ##
5
+ # High performance source code reloader middleware
6
+ #
7
+ module Reloader
8
+ ##
9
+ # This reloader is suited for use in a many environments because each file
10
+ # will only be checked once and only one system call to stat(2) is made.
11
+ #
12
+ # Please note that this will not reload files in the background, and does so
13
+ # only when explicitly invoked.
14
+ #
15
+ MTIMES = {}
16
+ LOADED_FILES = {}
17
+ LOADED_CLASSES = {}
18
+
19
+ class << self
20
+ ##
21
+ # Specified folders can be excluded from the code reload detection process.
22
+ # Default excluded directories at Padrino.root are: test, spec, features, tmp, config, db and public
23
+ #
24
+ def exclude
25
+ @_exclude ||= %w(test spec tmp features config public db).map { |path| Padrino.root(path) }
26
+ end
27
+
28
+ ##
29
+ # Specified constants can be excluded from the code unloading process.
30
+ #
31
+ def exclude_constants
32
+ @_exclude_constants ||= []
33
+ end
34
+
35
+ ##
36
+ # Specified constants can be configured to be reloaded on every request.
37
+ # Default included constants are: [none]
38
+ #
39
+ def include_constants
40
+ @_include_constants ||= []
41
+ end
42
+ ##
43
+ # Reload all files with changes detected.
44
+ #
45
+ def reload!
46
+ # Detect changed files
47
+ rotation do |file, mtime|
48
+ # Retrive the last modified time
49
+ new_file = MTIMES[file].nil?
50
+ previous_mtime = MTIMES[file] ||= mtime
51
+ logger.devel "Detected a new file #{file}" if new_file
52
+ # We skip to next file if it is not new and not modified
53
+ next unless new_file || mtime > previous_mtime
54
+ # Now we can reload our file
55
+ apps = mounted_apps_of(file)
56
+ if apps.present?
57
+ apps.each { |app| app.app_obj.reload! }
58
+ else
59
+ safe_load(file, :force => new_file)
60
+ # Reload also apps
61
+ Padrino.mounted_apps.each do |app|
62
+ app.app_obj.reload! if app.app_obj.dependencies.include?(file)
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ ##
69
+ # Remove files and classes loaded with stat
70
+ #
71
+ def clear!
72
+ MTIMES.clear
73
+ LOADED_CLASSES.each do |file, klasses|
74
+ klasses.each { |klass| remove_constant(klass) }
75
+ LOADED_CLASSES.delete(file)
76
+ end
77
+ LOADED_FILES.each do |file, dependencies|
78
+ dependencies.each { |dependency| $LOADED_FEATURES.delete(dependency) }
79
+ $LOADED_FEATURES.delete(file)
80
+ end
81
+ end
82
+
83
+ ##
84
+ # Returns true if any file changes are detected and populates the MTIMES cache
85
+ #
86
+ def changed?
87
+ changed = false
88
+ rotation do |file, mtime|
89
+ new_file = MTIMES[file].nil?
90
+ previous_mtime = MTIMES[file] ||= mtime
91
+ changed = true if new_file || mtime > previous_mtime
92
+ end
93
+ changed
94
+ end
95
+ alias :run! :changed?
96
+
97
+ ##
98
+ # We lock dependencies sets to prevent reloading of protected constants
99
+ #
100
+ def lock!
101
+ klasses = ObjectSpace.classes.map { |klass| klass.to_s.split("::")[0] }.uniq
102
+ klasses = klasses | Padrino.mounted_apps.map { |app| app.app_class }
103
+ Padrino::Reloader.exclude_constants.concat(klasses)
104
+ end
105
+
106
+ ##
107
+ # A safe Kernel::require which issues the necessary hooks depending on results
108
+ #
109
+ def safe_load(file, options={})
110
+ force, file = options[:force], figure_path(file)
111
+
112
+ # Check if file was changed or if force a reload
113
+ reload = MTIMES[file] && File.mtime(file) > MTIMES[file]
114
+ return if !force && !reload && MTIMES[file]
115
+
116
+ # Removes all classes declared in the specified file
117
+ if klasses = LOADED_CLASSES.delete(file)
118
+ klasses.each { |klass| remove_constant(klass) }
119
+ end
120
+
121
+ # Remove all loaded fatures with our file
122
+ if features = LOADED_FILES[file]
123
+ features.each { |feature| $LOADED_FEATURES.delete(feature) }
124
+ end
125
+
126
+ # Duplicate objects and loaded features before load file
127
+ klasses = ObjectSpace.classes.dup
128
+ files = $LOADED_FEATURES.dup
129
+
130
+ # Now we can reload dependencies of our file
131
+ if features = LOADED_FILES.delete(file)
132
+ features.each { |feature| safe_load(feature, :force => true) }
133
+ end
134
+
135
+ # And finally load the specified file
136
+ begin
137
+ logger.devel "Loading #{file}" if !reload
138
+ logger.debug "Reloading #{file}" if reload
139
+ $LOADED_FEATURES.delete(file)
140
+ verbosity_was, $-v = $-v, nil
141
+ loaded = false
142
+ require(file)
143
+ loaded = true
144
+ MTIMES[file] = File.mtime(file)
145
+ rescue SyntaxError => e
146
+ logger.error "Cannot require #{file} because of syntax error: #{e.message}"
147
+ ensure
148
+ $-v = verbosity_was
149
+ new_constants = (ObjectSpace.classes - klasses).uniq
150
+ if loaded
151
+ # Store the file details
152
+ LOADED_CLASSES[file] = new_constants
153
+ LOADED_FILES[file] = ($LOADED_FEATURES - files - [file]).uniq
154
+ # Track only features in our Padrino.root
155
+ LOADED_FILES[file].delete_if { |feature| !in_root?(feature) }
156
+ else
157
+ logger.devel "Failed to load #{file}; removing partially defined constants"
158
+ new_constants.each { |klass| remove_constant(klass) }
159
+ end
160
+
161
+ end
162
+ end
163
+
164
+ ##
165
+ # Returns true if the file is defined in our padrino root
166
+ #
167
+ def figure_path(file)
168
+ return file if Pathname.new(file).absolute?
169
+ $:.each do |path|
170
+ found = File.join(path, file)
171
+ return File.expand_path(found) if File.exist?(found)
172
+ end
173
+ file
174
+ end
175
+
176
+ ##
177
+ # Removes the specified class and constant.
178
+ #
179
+ def remove_constant(const)
180
+ return if exclude_constants.compact.uniq.any? { |c| (const.to_s =~ %r{^#{Regexp.escape(c)}}) } &&
181
+ !include_constants.compact.uniq.any? { |c| (const.to_s =~ %r{^#{Regexp.escape(c)}}) }
182
+ begin
183
+ parts = const.to_s.split("::")
184
+ base = parts.size == 1 ? Object : parts[0..-2].join("::").constantize
185
+ object = parts[-1].to_s
186
+ base.send(:remove_const, object)
187
+ logger.devel "Removed constant: #{const}"
188
+ rescue NameError; end
189
+ end
190
+
191
+ private
192
+ ##
193
+ # Return the mounted_apps providing the app location
194
+ # Can be an array because in one app.rb we can define multiple Padrino::Appplications
195
+ #
196
+ def mounted_apps_of(file)
197
+ file = figure_path(file)
198
+ Padrino.mounted_apps.find_all { |app| File.identical?(file, app.app_file) }
199
+ end
200
+
201
+ ##
202
+ # Returns true if file is in our Padrino.root
203
+ #
204
+ def in_root?(file)
205
+ # This is better but slow:
206
+ # Pathname.new(Padrino.root).find { |f| File.identical?(Padrino.root(f), figure_path(file)) }
207
+ figure_path(file) =~ %r{^#{Regexp.escape(Padrino.root)}}
208
+ end
209
+
210
+ ##
211
+ # Searches Ruby files in your +Padrino.load_paths+ , Padrino::Application.load_paths
212
+ # and monitors them for any changes.
213
+ #
214
+ def rotation
215
+ files = Padrino.load_paths.map { |path| Dir["#{path}/**/*.rb"] }.flatten
216
+ files = files | Padrino.mounted_apps.map { |app| app.app_file }
217
+ files = files | Padrino.mounted_apps.map { |app| app.app_obj.dependencies }.flatten
218
+ files.uniq.map { |file|
219
+ file = File.expand_path(file)
220
+ next if Padrino::Reloader.exclude.any? { |base| file =~ %r{^#{Regexp.escape(base)}} } || !File.exist?(file)
221
+ yield(file, File.mtime(file))
222
+ }.compact
223
+ end
224
+ end # self
225
+
226
+ ##
227
+ # This class acts as a Rack middleware to be added to the application stack. This middleware performs a
228
+ # check and reload for source files at the start of each request, but also respects a specified cool down time
229
+ # during which no further action will be taken.
230
+ #
231
+ class Rack
232
+ def initialize(app, cooldown=1)
233
+ @app = app
234
+ @cooldown = cooldown
235
+ @last = (Time.now - cooldown)
236
+ end
237
+
238
+ def call(env)
239
+ if @cooldown && Time.now > @last + @cooldown
240
+ Thread.list.size > 1 ? Thread.exclusive { Padrino.reload! } : Padrino.reload!
241
+ @last = Time.now
242
+ end
243
+ @app.call(env)
244
+ end
245
+ end
246
+ end # Reloader
247
+ end # Padrino
@@ -0,0 +1,79 @@
1
+ module Padrino
2
+ ##
3
+ # This class is an extended version of Rack::URLMap
4
+ #
5
+ # Padrino::Router like Rack::URLMap dispatches in such a way that the
6
+ # longest paths are tried first, since they are most specific.
7
+ #
8
+ # Features:
9
+ #
10
+ # * Map a path to the specified App
11
+ # * Ignore server names (this solve issues with vhost and domain aliases)
12
+ # * Use hosts instead of server name for mappings (this help us with our vhost and doman aliases)
13
+ #
14
+ # ==== Options
15
+ #
16
+ # :to:: The class of application that you want mount
17
+ # :path:: Map the app to the given path
18
+ # :host:: Map the app to the given host
19
+ #
20
+ # ==== Examples
21
+ #
22
+ # routes = Padrino::Router.new do
23
+ # map(:path => "/", :to => PadrinoWeb, :host => "padrino.local")
24
+ # map(:path => "/", :to => Admin, :host => "admin.padrino.local")
25
+ # end
26
+ # run routes
27
+ #
28
+ # routes = Padrino::Router.new do
29
+ # map(:path => "/", :to => PadrinoWeb, :host => /*.padrino.local/)
30
+ # end
31
+ # run routes
32
+ #
33
+ class Router
34
+ def initialize(*mapping, &block)
35
+ @mapping = []
36
+ mapping.each { |m| map(m) }
37
+ instance_eval(&block) if block
38
+ end
39
+
40
+ def sort!
41
+ @mapping = @mapping.sort_by { |h, p, m, a| -p.size }
42
+ end
43
+
44
+ def map(options={})
45
+ path = options[:path] || "/"
46
+ host = options[:host]
47
+ app = options[:to]
48
+
49
+ raise ArgumentError, "paths need to start with /" if path[0] != ?/
50
+ raise ArgumentError, "app is required" if app.nil?
51
+
52
+ path = path.chomp('/')
53
+ match = Regexp.new("^#{Regexp.quote(path).gsub('/', '/+')}(.*)", nil, 'n')
54
+ host = Regexp.new("^#{Regexp.quote(host)}$", true, 'n') unless host.nil? || host.is_a?(Regexp)
55
+
56
+ @mapping << [host, path, match, app]
57
+ sort!
58
+ end
59
+
60
+ def call(env)
61
+ rPath = env["PATH_INFO"].to_s
62
+ script_name = env['SCRIPT_NAME']
63
+ hHost, sName, sPort = env.values_at('HTTP_HOST','SERVER_NAME','SERVER_PORT')
64
+ @mapping.each do |host, path, match, app|
65
+ next unless host.nil? || hHost =~ host
66
+ next unless rPath =~ match && rest = $1
67
+ next unless rest.empty? || rest[0] == ?/
68
+
69
+ rest = "/" if rest.empty?
70
+
71
+ return app.call(
72
+ env.merge(
73
+ 'SCRIPT_NAME' => (script_name + path),
74
+ 'PATH_INFO' => rest))
75
+ end
76
+ [404, {"Content-Type" => "text/plain", "X-Cascade" => "pass"}, ["Not Found: #{rPath}"]]
77
+ end
78
+ end # Router
79
+ end # Padrino