riojs 0.0.0

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 (270) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +24 -0
  3. data/VERSION +1 -0
  4. data/bin/rio +5 -0
  5. data/generators/rio_app/USAGE +19 -0
  6. data/generators/rio_app/rio_app_generator.rb +40 -0
  7. data/generators/rio_app/templates/app.build +10 -0
  8. data/generators/rio_app/templates/app.css +0 -0
  9. data/generators/rio_app/templates/app.js +20 -0
  10. data/generators/rio_app/templates/app_view.html.erb +19 -0
  11. data/generators/rio_app/templates/fixture.js +4 -0
  12. data/generators/rio_app/templates/rio.html.erb +18 -0
  13. data/generators/rio_app/templates/rio_controller.rb +2 -0
  14. data/generators/rio_app/templates/spec.js +7 -0
  15. data/generators/rio_component/USAGE +13 -0
  16. data/generators/rio_component/rio_component_generator.rb +16 -0
  17. data/generators/rio_component/templates/component.css +0 -0
  18. data/generators/rio_component/templates/component.js +11 -0
  19. data/generators/rio_component/templates/fixture.js +3 -0
  20. data/generators/rio_component/templates/spec.js +6 -0
  21. data/generators/rio_model/USAGE +12 -0
  22. data/generators/rio_model/rio_model_generator.rb +21 -0
  23. data/generators/rio_model/templates/fixture.js +3 -0
  24. data/generators/rio_model/templates/model.js +9 -0
  25. data/generators/rio_model/templates/spec.js +6 -0
  26. data/generators/rio_page/USAGE +14 -0
  27. data/generators/rio_page/rio_page_generator.rb +16 -0
  28. data/generators/rio_page/templates/fixture.js +3 -0
  29. data/generators/rio_page/templates/page.css +12 -0
  30. data/generators/rio_page/templates/page.js +12 -0
  31. data/generators/rio_page/templates/page.jst +64 -0
  32. data/generators/rio_page/templates/spec.js +6 -0
  33. data/generators/rio_resource/USAGE +20 -0
  34. data/generators/rio_resource/rio_resource_generator.rb +10 -0
  35. data/generators/rio_resource/templates/controller.rb +3 -0
  36. data/init.rb +4 -0
  37. data/install/config/juggernaut_hosts.yml +18 -0
  38. data/install/lib/tasks/rio.rake +1 -0
  39. data/install/script/rio_server +37 -0
  40. data/lib/rio/autospec.rb +86 -0
  41. data/lib/rio/install.rb +90 -0
  42. data/lib/rio/juggernaut.rb +212 -0
  43. data/lib/rio/path.rb +3 -0
  44. data/lib/rio/rio_compressor.rb +219 -0
  45. data/lib/rio/rio_file_controller.rb +16 -0
  46. data/lib/rio/rio_on_rails.rb +586 -0
  47. data/lib/rio/rio_proxy_controller.rb +60 -0
  48. data/lib/rio/rio_push_controller.rb +48 -0
  49. data/lib/rio/rio_routes.rb +24 -0
  50. data/lib/rio/rio_spec_controller.rb +70 -0
  51. data/lib/riojs.rb +14 -0
  52. data/lib/tasks/rio.rb +63 -0
  53. data/public/images/background-chiffon.png +0 -0
  54. data/public/images/button-gradient-overlay-down.png +0 -0
  55. data/public/images/button-gradient-overlay.png +0 -0
  56. data/public/images/icons/add.png +0 -0
  57. data/public/images/icons/error-big.png +0 -0
  58. data/public/images/icons/warning-big.png +0 -0
  59. data/public/images/rio-logo-big.png +0 -0
  60. data/public/images/rio-logo.png +0 -0
  61. data/public/images/splitter-handle-horizontal.png +0 -0
  62. data/public/images/splitter-handle-vertical.png +0 -0
  63. data/public/images/tab-bar-gradient-overlay.png +0 -0
  64. data/public/images/title-gradient-overlay.png +0 -0
  65. data/public/images/trash.gif +0 -0
  66. data/public/javascripts/components/accordion.js +144 -0
  67. data/public/javascripts/components/alert_box.js +59 -0
  68. data/public/javascripts/components/base.js +47 -0
  69. data/public/javascripts/components/box.js +63 -0
  70. data/public/javascripts/components/button.js +98 -0
  71. data/public/javascripts/components/checkbox.js +44 -0
  72. data/public/javascripts/components/container.js +265 -0
  73. data/public/javascripts/components/grid_view.js +107 -0
  74. data/public/javascripts/components/image.js +19 -0
  75. data/public/javascripts/components/input.js +171 -0
  76. data/public/javascripts/components/label.js +15 -0
  77. data/public/javascripts/components/lightbox.js +160 -0
  78. data/public/javascripts/components/link.js +43 -0
  79. data/public/javascripts/components/list_item.js +44 -0
  80. data/public/javascripts/components/list_view.js +192 -0
  81. data/public/javascripts/components/marquee.js +131 -0
  82. data/public/javascripts/components/menu.js +89 -0
  83. data/public/javascripts/components/notification.js +75 -0
  84. data/public/javascripts/components/overlay.js +134 -0
  85. data/public/javascripts/components/panel.js +146 -0
  86. data/public/javascripts/components/radio.js +46 -0
  87. data/public/javascripts/components/splitter.js +65 -0
  88. data/public/javascripts/components/tab_bar.js +64 -0
  89. data/public/javascripts/components/tab_panel.js +57 -0
  90. data/public/javascripts/components/textarea.js +223 -0
  91. data/public/javascripts/components/toggle_button.js +22 -0
  92. data/public/javascripts/components/tooltip.js +80 -0
  93. data/public/javascripts/lib/application.js +482 -0
  94. data/public/javascripts/lib/attr.js +760 -0
  95. data/public/javascripts/lib/benchmark.js +235 -0
  96. data/public/javascripts/lib/blank.html +39 -0
  97. data/public/javascripts/lib/boot.js +300 -0
  98. data/public/javascripts/lib/clipboard.js +96 -0
  99. data/public/javascripts/lib/collection_entity.js +46 -0
  100. data/public/javascripts/lib/component.js +129 -0
  101. data/public/javascripts/lib/console.js +75 -0
  102. data/public/javascripts/lib/console/apps/console.build +43 -0
  103. data/public/javascripts/lib/console/apps/console.js +28 -0
  104. data/public/javascripts/lib/console/blank.html +39 -0
  105. data/public/javascripts/lib/console/components/benchmark.js +196 -0
  106. data/public/javascripts/lib/console/components/console.js +352 -0
  107. data/public/javascripts/lib/console/components/dependencies_list.js +17 -0
  108. data/public/javascripts/lib/console/components/docs.js +66 -0
  109. data/public/javascripts/lib/console/components/playground.js +30 -0
  110. data/public/javascripts/lib/console/console.html +27 -0
  111. data/public/javascripts/lib/console/console_commands.js +287 -0
  112. data/public/javascripts/lib/console/console_commands.js.rej +21 -0
  113. data/public/javascripts/lib/console/console_mixin.js +22 -0
  114. data/public/javascripts/lib/console/docs/files.html +579 -0
  115. data/public/javascripts/lib/console/docs/index.html +323 -0
  116. data/public/javascripts/lib/console/docs/symbols/Object.html +291 -0
  117. data/public/javascripts/lib/console/docs/symbols/_global_.html +413 -0
  118. data/public/javascripts/lib/console/docs/symbols/rio.AIM.html +490 -0
  119. data/public/javascripts/lib/console/docs/symbols/rio.Application.html +841 -0
  120. data/public/javascripts/lib/console/docs/symbols/rio.Attr.html +1075 -0
  121. data/public/javascripts/lib/console/docs/symbols/rio.Binding.html +272 -0
  122. data/public/javascripts/lib/console/docs/symbols/rio.Component.html +419 -0
  123. data/public/javascripts/lib/console/docs/symbols/rio.Cookie.html +543 -0
  124. data/public/javascripts/lib/console/docs/symbols/rio.DelayedTask#initialize.html +270 -0
  125. data/public/javascripts/lib/console/docs/symbols/rio.DelayedTask.html +391 -0
  126. data/public/javascripts/lib/console/docs/symbols/rio.JsTemplate.html +271 -0
  127. data/public/javascripts/lib/console/docs/symbols/rio.Juggernaut.html +329 -0
  128. data/public/javascripts/lib/console/docs/symbols/rio.Model.html +822 -0
  129. data/public/javascripts/lib/console/docs/symbols/rio.Page.html +383 -0
  130. data/public/javascripts/lib/console/docs/symbols/rio.Template.html +328 -0
  131. data/public/javascripts/lib/console/docs/symbols/rio.Utils.html +617 -0
  132. data/public/javascripts/lib/console/docs/symbols/rio.html +506 -0
  133. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_components_base.js.html +54 -0
  134. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_application.js.html +490 -0
  135. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_attr.js.html +768 -0
  136. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_boot.js.html +308 -0
  137. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_clipboard.js.html +103 -0
  138. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_collection_entity.js.html +53 -0
  139. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_component.js.html +137 -0
  140. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_cookie.js.html +81 -0
  141. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_delayed_task.js.html +68 -0
  142. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_file.js.html +80 -0
  143. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_flash_detect.js.html +129 -0
  144. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_form.js.html +95 -0
  145. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_id.js.html +50 -0
  146. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_inflector.js.html +167 -0
  147. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_js_template.js.html +283 -0
  148. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_juggernaut.js.html +303 -0
  149. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_key_map.js.html +68 -0
  150. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_layout_manager.js.html +175 -0
  151. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_log.js.html +17 -0
  152. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_model.js.html +1074 -0
  153. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_page.js.html +246 -0
  154. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_parameters.js.html +66 -0
  155. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_protohack.js.html +305 -0
  156. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_push.js.html +12 -0
  157. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_rsh.js.html +659 -0
  158. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_swfobject.js.html +12 -0
  159. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_tag.js.html +60 -0
  160. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_template.js.html +64 -0
  161. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_theme.js.html +105 -0
  162. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_undo.js.html +142 -0
  163. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_utils.js.html +87 -0
  164. data/public/javascripts/lib/console/docs/symbols/src/public_javascripts_lib_yaml.js.html +88 -0
  165. data/public/javascripts/lib/console/file-small.png +0 -0
  166. data/public/javascripts/lib/console/green-circle.png +0 -0
  167. data/public/javascripts/lib/console/loading.gif +0 -0
  168. data/public/javascripts/lib/console/pages/console_page.js +149 -0
  169. data/public/javascripts/lib/console/pages/console_page.jst +27 -0
  170. data/public/javascripts/lib/console/red-circle.png +0 -0
  171. data/public/javascripts/lib/cookie.js +74 -0
  172. data/public/javascripts/lib/delayed_task.js +61 -0
  173. data/public/javascripts/lib/dependencies.js +76 -0
  174. data/public/javascripts/lib/environment.js +30 -0
  175. data/public/javascripts/lib/event.simulate.js +137 -0
  176. data/public/javascripts/lib/expressinstall.swf +0 -0
  177. data/public/javascripts/lib/file.js +72 -0
  178. data/public/javascripts/lib/flash_detect.js +122 -0
  179. data/public/javascripts/lib/flashembed.min.js +16 -0
  180. data/public/javascripts/lib/form.js +88 -0
  181. data/public/javascripts/lib/id.js +43 -0
  182. data/public/javascripts/lib/inflector.js +160 -0
  183. data/public/javascripts/lib/instrumenter.js +106 -0
  184. data/public/javascripts/lib/js_template.js +275 -0
  185. data/public/javascripts/lib/jslint.js +4950 -0
  186. data/public/javascripts/lib/juggernaut.js +295 -0
  187. data/public/javascripts/lib/juggernaut.swf +0 -0
  188. data/public/javascripts/lib/key_map.js +60 -0
  189. data/public/javascripts/lib/layout_manager.js +167 -0
  190. data/public/javascripts/lib/model.js +1067 -0
  191. data/public/javascripts/lib/page.js +238 -0
  192. data/public/javascripts/lib/parameters.js +59 -0
  193. data/public/javascripts/lib/png_fix.js +75 -0
  194. data/public/javascripts/lib/protohack.js +297 -0
  195. data/public/javascripts/lib/push.js +5 -0
  196. data/public/javascripts/lib/rio.build +28 -0
  197. data/public/javascripts/lib/rio_development.build +5 -0
  198. data/public/javascripts/lib/rio_lint.js +66 -0
  199. data/public/javascripts/lib/rsh.js +651 -0
  200. data/public/javascripts/lib/spec.js +545 -0
  201. data/public/javascripts/lib/spec_runner.js +242 -0
  202. data/public/javascripts/lib/swfobject.js +5 -0
  203. data/public/javascripts/lib/tag.js +52 -0
  204. data/public/javascripts/lib/undo.js +134 -0
  205. data/public/javascripts/lib/utils.js +80 -0
  206. data/public/javascripts/lib/yaml.js +80 -0
  207. data/public/javascripts/pages/playground_page.js +15 -0
  208. data/public/javascripts/prototype/builder.js +146 -0
  209. data/public/javascripts/prototype/controls.js +1004 -0
  210. data/public/javascripts/prototype/dragdrop.js +1030 -0
  211. data/public/javascripts/prototype/effects.js +1137 -0
  212. data/public/javascripts/prototype/prototype.js +4320 -0
  213. data/public/javascripts/prototype/slider.js +283 -0
  214. data/public/javascripts/prototype/sound.js +67 -0
  215. data/public/javascripts/specs/components/box_spec.js +6 -0
  216. data/public/javascripts/specs/components/checkbox_spec.js +26 -0
  217. data/public/javascripts/specs/components/container_spec.js +6 -0
  218. data/public/javascripts/specs/components/input_spec.js +71 -0
  219. data/public/javascripts/specs/components/panel_spec.js +6 -0
  220. data/public/javascripts/specs/components/radio_spec.js +40 -0
  221. data/public/javascripts/specs/fixtures/components/box.js +3 -0
  222. data/public/javascripts/specs/fixtures/components/checkbox.js +9 -0
  223. data/public/javascripts/specs/fixtures/components/container.js +3 -0
  224. data/public/javascripts/specs/fixtures/components/input.js +12 -0
  225. data/public/javascripts/specs/fixtures/components/menu.js +19 -0
  226. data/public/javascripts/specs/fixtures/components/menu_item.js +18 -0
  227. data/public/javascripts/specs/fixtures/components/radio.js +11 -0
  228. data/public/javascripts/specs/lib/application_spec.js +281 -0
  229. data/public/javascripts/specs/lib/attr_spec.js +1514 -0
  230. data/public/javascripts/specs/lib/benchmark_spec.js +361 -0
  231. data/public/javascripts/specs/lib/collection_entity_spec.js +131 -0
  232. data/public/javascripts/specs/lib/component_spec.js +86 -0
  233. data/public/javascripts/specs/lib/form_spec.js +171 -0
  234. data/public/javascripts/specs/lib/id_spec.js +21 -0
  235. data/public/javascripts/specs/lib/instrumenter_spec.js +5 -0
  236. data/public/javascripts/specs/lib/js_template_spec.js +131 -0
  237. data/public/javascripts/specs/lib/key_map_spec.js +227 -0
  238. data/public/javascripts/specs/lib/model_spec.js +2268 -0
  239. data/public/javascripts/specs/lib/parameters_spec.js +94 -0
  240. data/public/javascripts/specs/lib/spec_spec.js +943 -0
  241. data/public/javascripts/specs/lib/undo_spec.js +105 -0
  242. data/public/javascripts/specs/lib/yaml_spec.js +127 -0
  243. data/public/sounds/basso.wav +0 -0
  244. data/public/sounds/purr.wav +0 -0
  245. data/public/stylesheets/components/accordion.css +24 -0
  246. data/public/stylesheets/components/alert_box.css +35 -0
  247. data/public/stylesheets/components/box.css +0 -0
  248. data/public/stylesheets/components/button.css +39 -0
  249. data/public/stylesheets/components/checkbox.css +9 -0
  250. data/public/stylesheets/components/container.css +3 -0
  251. data/public/stylesheets/components/grid_view.css +52 -0
  252. data/public/stylesheets/components/input.css +10 -0
  253. data/public/stylesheets/components/label.css +3 -0
  254. data/public/stylesheets/components/lightbox.css +31 -0
  255. data/public/stylesheets/components/link.css +4 -0
  256. data/public/stylesheets/components/list_view.css +23 -0
  257. data/public/stylesheets/components/marquee.css +29 -0
  258. data/public/stylesheets/components/menu.css +34 -0
  259. data/public/stylesheets/components/notification.css +52 -0
  260. data/public/stylesheets/components/overlay.css +8 -0
  261. data/public/stylesheets/components/panel.css +36 -0
  262. data/public/stylesheets/components/radio.css +9 -0
  263. data/public/stylesheets/components/splitter.css +35 -0
  264. data/public/stylesheets/components/tab_bar.css +59 -0
  265. data/public/stylesheets/components/tab_panel.css +15 -0
  266. data/public/stylesheets/components/textarea.css +11 -0
  267. data/public/stylesheets/components/tooltip.css +10 -0
  268. data/public/stylesheets/console.css +151 -0
  269. data/public/stylesheets/css_reset.css +55 -0
  270. metadata +343 -0
data/lib/rio/path.rb ADDED
@@ -0,0 +1,3 @@
1
+ module Rio
2
+ ROOT = File.join(File.dirname(__FILE__), "..", "..")
3
+ end
@@ -0,0 +1,219 @@
1
+ # =================================================================
2
+ # = This file has a lot of repetition in it. Refactoring needed! =
3
+ # =================================================================
4
+ class RioCompressor
5
+ def self.concat_scripts(scripts, digestName)
6
+ line_number = 1
7
+ scripts.map do |script|
8
+ currently_parsing = script.match(/.*\/javascripts\/(.*)\.js$/)[1]
9
+ digest_entry = "rio.boot.#{digestName}['#{line_number + 1}'] = '#{currently_parsing}';\n"
10
+ content = File.open(script).read + "\n"
11
+ line_number = line_number + content.split("\n").size + 1
12
+
13
+ digest_entry + content
14
+ end.join("\n\n")
15
+ end
16
+
17
+ def self.concat_scripts_for_minify(scripts)
18
+ scripts.map do |script|
19
+ File.open(script).read
20
+ end.join("\n\n")
21
+ end
22
+
23
+ def self.minify_boot
24
+ prototype_file = File.join(RIO_JS_ROOT, "prototype", "prototype.js")
25
+ environment_file = File.join(JS_ROOT, "lib", "environment.js")
26
+ boot_file = File.join(RIO_JS_ROOT, "lib", "boot.js")
27
+ compressed_prototype_file = File.join(JS_ROOT, "prototype", "compressed", "prototype.js")
28
+ compressed_rio_file = File.join(JS_ROOT, "lib", "compressed", "rio.js")
29
+
30
+ self.minify_scripts(self.prototype_scripts, compressed_prototype_file)
31
+ self.minify_scripts(self.rio_scripts, compressed_rio_file)
32
+
33
+ compressed_boot_file = File.join(JS_ROOT, "lib", "compressed", "boot.js")
34
+ unless File.exists?(File.dirname(compressed_boot_file))
35
+ FileUtils.mkdir_p(File.dirname(compressed_boot_file))
36
+ end
37
+ File.open(compressed_boot_file, "w") do |f|
38
+ f.puts self.concat_scripts_for_minify([
39
+ prototype_file,
40
+ environment_file,
41
+ boot_file,
42
+ compressed_prototype_file,
43
+ # compressed_rio_file
44
+ ])
45
+ end
46
+ end
47
+
48
+ def self.minify_scripts(scripts, compressed_script)
49
+ code = concat_scripts_for_minify(scripts)
50
+
51
+ compressed = Packr.pack(code)
52
+
53
+ unless File.exists?(File.dirname(compressed_script))
54
+ FileUtils.mkdir_p(File.dirname(compressed_script))
55
+ end
56
+ File.open(compressed_script, "w") do |f|
57
+ f.puts compressed
58
+ end
59
+ end
60
+
61
+ def self.minify_stylesheets(app, path, stylesheet_path)
62
+ unless File.exists?(File.dirname(stylesheet_path))
63
+ FileUtils.mkdir_p(File.dirname(stylesheet_path))
64
+ end
65
+ File.open(stylesheet_path, "w") do |f|
66
+ f.puts concat_stylesheets_for_app(app, path)
67
+ end
68
+ end
69
+
70
+ def self.minify_templates(app, path, template_path)
71
+ unless File.exists?(File.dirname(template_path))
72
+ FileUtils.mkdir_p(File.dirname(template_path))
73
+ end
74
+ File.open(template_path, "w") do |f|
75
+ f.puts concat_templates_for_app(app, path)
76
+ end
77
+ end
78
+
79
+ def self.read_build_file(build_file)
80
+ File.readlines(build_file).reject(&:blank?).map(&:strip)
81
+ end
82
+
83
+
84
+ def self.rio_scripts
85
+ self.raw_rio_scripts.map {|f| File.join(self.rio_js_root, f + ".js") }
86
+ end
87
+ def self.raw_rio_scripts
88
+ self.read_build_file(File.join(self.rio_js_root, "lib", "rio.build"))
89
+ end
90
+
91
+
92
+ def self.rio_development_scripts
93
+ self.raw_rio_development_scripts.map {|f| File.join(self.rio_js_root, f + ".js") }
94
+ end
95
+ def self.raw_rio_development_scripts
96
+ self.read_build_file(File.join(self.rio_js_root, "lib", "rio_development.build"))
97
+ end
98
+
99
+
100
+ def self.prototype_scripts
101
+ self.raw_prototype_scripts.map do |f|
102
+ File.join(self.rio_js_root, f + ".js")
103
+ end
104
+ end
105
+ def self.raw_prototype_scripts
106
+ ["prototype/effects", "prototype/dragdrop", "prototype/controls", "prototype/builder"]
107
+ end
108
+
109
+ def self.apps
110
+ Dir.entries(File.join(self.js_root, "apps")).select { |e| e.match(/.*\.build$/) }.map { |e| e.match(/(.*)\.build$/)[1] }
111
+ end
112
+
113
+ def self.scripts_for_app(app, path)
114
+ self.raw_scripts_for_app(app, path).map do |f|
115
+ self.script_for_app(f)
116
+ end
117
+ end
118
+ def self.script_for_app(script)
119
+ File.exists?(File.join(self.js_root, script + ".js")) ? File.join(self.js_root, script + ".js") : File.join(self.rio_js_root, script + ".js")
120
+ end
121
+ def self.raw_scripts_for_app(app, path)
122
+ self.yaml_for_app(app, path)["scripts"]
123
+ end
124
+ def self.yaml_for_app(app, path)
125
+ app_build_path = File.join(self.js_root, path - [path.last], app + ".build")
126
+ rio_build_path = File.join(self.rio_js_root, path - [path.last], app + ".build")
127
+
128
+ filename = File.exists?(app_build_path) ? app_build_path : rio_build_path
129
+ YAML.load_file(filename)
130
+ end
131
+
132
+ def self.concat_script_functions_for_app(app, path)
133
+ register = raw_scripts_for_app(app, path).map do |f|
134
+ <<-JS
135
+ rio.boot.loadFunctions['#{f}'] = function() {
136
+ #{File.open(self.script_for_app(f)).read}
137
+ };
138
+ JS
139
+ end.join("\n\n")
140
+ end
141
+
142
+ def self.stylesheet_files_for_app(app, path)
143
+ self.yaml_for_app(app, path)["stylesheets"] || []
144
+ end
145
+ def self.concat_stylesheets_for_app(app, path)
146
+ stylesheet_files_for_app(app, path).map do |t|
147
+ content_of_stylesheet(t)
148
+ end.join("\n")
149
+ end
150
+ def self.content_of_stylesheet(t)
151
+ sub_path = File.join("public", "stylesheets", t + ".css")
152
+ app_path = File.join(self.root, sub_path)
153
+ rio_path = File.join(self.rio_root, sub_path)
154
+
155
+ File.read(File.exists?(app_path) ? app_path : rio_path)
156
+ end
157
+
158
+ def self.template_files_for_app(app, path)
159
+ self.yaml_for_app(app, path)["templates"] || []
160
+ end
161
+ def self.concat_templates_for_app(app, path)
162
+ "<templates xmlns:rio=\"http://riojs.com\">" + template_files_for_app(app, path).map do |t|
163
+ tag_name = t.gsub("/", "--")
164
+ class_name = t.split("/").last.camelize(:lower)
165
+ <<-JST
166
+ <#{tag_name}>
167
+ <div style="height: 100%;" class="#{class_name}">
168
+ #{content_of_template(t)}
169
+ </div>
170
+ </#{tag_name}>
171
+ JST
172
+ end.join("\n") + "</templates>"
173
+ end
174
+ def self.content_of_template(t)
175
+ app_path = File.join(self.js_root, t + ".jst")
176
+ rio_path = File.join(self.rio_js_root, t + ".jst")
177
+
178
+ File.read(File.exists?(app_path) ? app_path : rio_path)
179
+ end
180
+
181
+ def self.concat_scripts_for_rio
182
+ register = (self.raw_rio_scripts + self.raw_rio_development_scripts).map do |s|
183
+ "rio.boot.loadedFiles.push('#{s}');rio.boot.rioScripts.push('#{s}');"
184
+ end.join("\n")
185
+ register + "\n" + self.concat_scripts(self.rio_scripts + self.rio_development_scripts, "rioScriptsDigest")
186
+ end
187
+
188
+ def self.concat_scripts_for_rio_development
189
+ register = (self.raw_rio_development_scripts).map do |s|
190
+ "rio.boot.loadedFiles.push('#{s}');rio.boot.rioScripts.push('#{s}');"
191
+ end.join("\n")
192
+ register + "\n" + self.concat_scripts(self.rio_development_scripts, "appScriptsDigest")
193
+ end
194
+
195
+ def self.concat_scripts_for_prototype
196
+ register = self.raw_prototype_scripts.map do |s|
197
+ "rio.boot.loadedFiles.push('#{s}');rio.boot.prototypeScripts.push('#{s}');"
198
+ end.join("\n")
199
+ register + "\n" + self.concat_scripts(self.prototype_scripts, "prototypeScriptsDigest")
200
+ end
201
+
202
+ private
203
+
204
+ def self.root
205
+ RAILS_ROOT
206
+ end
207
+
208
+ def self.rio_root
209
+ Rio::ROOT
210
+ end
211
+
212
+ def self.js_root
213
+ File.join(root, "public", "javascripts")
214
+ end
215
+
216
+ def self.rio_js_root
217
+ File.join(rio_root, "public", "javascripts")
218
+ end
219
+ end
@@ -0,0 +1,16 @@
1
+ class RioFileController < ApplicationController
2
+ ssl_allowed :write if defined? SslRequirement
3
+ protect_from_forgery :except => :write
4
+
5
+ def write
6
+ app_path = File.join(Rio::ROOT, "public", params[:path])
7
+ rio_path = File.join(RAILS_ROOT, "public", params[:path])
8
+
9
+ File.open(File.exists?(app_path) ? app_path : rio_path, "w") do |f|
10
+ f.write(params[:content])
11
+ end
12
+
13
+ render :text => "SUCCESS"
14
+ end
15
+
16
+ end
@@ -0,0 +1,586 @@
1
+ # RioOnRails
2
+ require 'digest/sha1'
3
+ require 'json/add/rails'
4
+
5
+ module Rio
6
+ module Helpers
7
+ def cache_key
8
+ @cache_key ||= ENV['cache_rio'] ? File.new(RAILS_ROOT).mtime.to_i : rand
9
+ end
10
+
11
+ def application_stylesheet
12
+ url = boot_compressed? ? "compressed/#{@rio_app}.css" : "#{@rio_app}_concat.css"
13
+ <<-CSS
14
+ <link href="#{asset_prefix}/stylesheets/#{url}?#{cache_key}" media="screen" rel="stylesheet" type="text/css" />
15
+ CSS
16
+ end
17
+
18
+ def asset_prefix
19
+ # meant to be overriden
20
+ ""
21
+ end
22
+
23
+ def after_rio(html)
24
+ @after_rio = "#{@after_rio || ""}\n#{html}"
25
+ end
26
+
27
+ def boot_compressed?
28
+ rio_compression == "compressed"
29
+ end
30
+
31
+ def rio_compression
32
+ ENV['rio_compression'] || ((RAILS_ENV == "development" and params.has_key?(:compressed)) ? "compressed" : "uncompressed")
33
+ end
34
+
35
+ def rio_environment
36
+ ENV['rio_environment'] || RAILS_ENV
37
+ end
38
+
39
+ def rio(opts = {})
40
+ if @rio_app
41
+ rio_html = <<-HTML
42
+ <script type="text/javascript">
43
+ rio = {
44
+ cacheKey: "#{cache_key}",
45
+ assetPrefix: "#{asset_prefix}",
46
+ preloadedStylesheets: #{RioCompressor.stylesheet_files_for_app(@rio_app, ["apps", @rio_app + ".build"]).to_json},
47
+ preloadTemplates: #{not RioCompressor.template_files_for_app(@rio_app, ["apps", @rio_app + ".build"]).empty?},
48
+ environment: {
49
+ includeRootInJson: "#{ ActiveRecord::Base.include_root_in_json }",
50
+ railsToken: "#{ form_authenticity_token }",
51
+ sessionId: #{ session.session_id.to_json },
52
+ uSessionId: "#{ u session.session_id }",
53
+ transactionKey: "#{ u Digest::SHA1.hexdigest(Time.now.to_f.to_s + session.session_id) }"
54
+ }
55
+ };
56
+ #{ current_user_id.blank? ? "" : "rio.environment.userId = #{ current_user_id }" };
57
+ </script>
58
+ HTML
59
+
60
+ if (boot_compressed?)
61
+ <<-SCRIPTS
62
+ #{rio_html}
63
+ #{javascript_include_tag "#{asset_prefix}/javascripts/lib/compressed/boot.js?#{@rio_app},#{rio_environment},#{rio_compression},#{cache_key}"}
64
+ #{@after_rio || ""}
65
+ SCRIPTS
66
+ else
67
+ <<-SCRIPTS
68
+ #{rio_html}
69
+ #{javascript_include_tag "prototype/prototype.js"}
70
+ #{javascript_include_tag "lib/environment.js"}
71
+ #{javascript_include_tag "lib/boot.js?#{@rio_app},#{rio_environment},#{rio_compression},#{cache_key}"}
72
+ #{@after_rio || ""}
73
+ SCRIPTS
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ module ActiveRecordExtensions
80
+ def self.included(base)
81
+ base.extend ClassMethods
82
+ base.send(:include, Rio::ActiveRecordExtensions::Methods)
83
+ end
84
+
85
+ module ClassMethods
86
+
87
+ def rio_json(options = {})
88
+ self.send(:cattr_accessor, :rio_json_includes)
89
+
90
+ self.rio_json_includes = options[:include]
91
+
92
+ self.send(:include, Rio::RioModel)
93
+ end
94
+
95
+ def broadcast(mode)
96
+ self.send(:cattr_accessor, :broadcast_mode)
97
+ self.broadcast_mode = mode
98
+ end
99
+
100
+ def broadcast_mode
101
+ :normal
102
+ end
103
+
104
+ def broadcast?
105
+ self.broadcast_mode != :none
106
+ end
107
+
108
+ def validate_transaction!(transaction, objects)
109
+ true
110
+ end
111
+ end
112
+
113
+ module Methods
114
+ def broadcast_to
115
+ []
116
+ end
117
+ end
118
+ end
119
+
120
+ module RioModel
121
+ # cattr_accessor :rio_json_includes
122
+ def has_json_options?
123
+ self.class.respond_to?("json_options")
124
+ end
125
+
126
+ def json_options
127
+ has_json_options? ? self.class.json_options : {}
128
+ end
129
+
130
+ def json_hash
131
+ result = ActiveRecord::Serialization::Serializer.new(self, json_options).serializable_record
132
+
133
+ # result = Hash.new
134
+ # self.class.columns.each do |column|
135
+ # # unless column.name == "created_at" || column.name == "updated_at"
136
+ # result[column.name.to_sym] = self.send(column.name)
137
+ # # end
138
+ # end
139
+
140
+ # if(has_json_options)
141
+ # (self.class.json_options[:methods] || []).each do |method|
142
+ # result[method.to_sym] = self.send(method)
143
+ # end
144
+ # end
145
+
146
+ ActiveRecord::Base.include_root_in_json ? { self.class.name.underscore => result } : result
147
+ end
148
+
149
+ def include_json
150
+ self.class.rio_json_includes.map do |inc|
151
+ {
152
+ :className => inc[:class_name],
153
+ :parameters => inc[:params].keys.inject({}) do |acc, k|
154
+ val = inc[:params][k]
155
+ acc[k] = val.class == Proc ? val.call(self) : val
156
+ acc
157
+ end,
158
+ :json => self.send(inc[:name])
159
+ }
160
+ end
161
+ end
162
+
163
+ def to_json(*args)
164
+ if self.class.rio_json_includes.nil? or self.class.rio_json_includes.empty?
165
+ json_hash.to_json
166
+ else
167
+ {
168
+ :_set => {
169
+ :self => json_hash,
170
+ :include => include_json
171
+ }
172
+ }.to_json
173
+ end
174
+ end
175
+ end
176
+
177
+ module ActionControllerExtensions
178
+ def rio_resource(options = {})
179
+ self.send(:cattr_accessor, :rio_actions)
180
+
181
+ self.rio_actions = options[:only] || [:index, :show, :create, :update, :destroy]
182
+ self.send(:include, Rio::RioResource)
183
+ end
184
+ end
185
+
186
+ module ApplicationControllerExtensions
187
+ def self.included(base)
188
+ base.send(:include, Rio::ApplicationControllerExtensions::Methods)
189
+ base.send(:helper_method, :current_user_id)
190
+
191
+ base.send(:before_filter, :reset_rio_cache)
192
+ end
193
+ module Methods
194
+ def current_user_id
195
+ nil
196
+ end
197
+
198
+ def reset_rio_cache
199
+ Thread.current[:current_user_id] = current_user_id
200
+ end
201
+ end
202
+ end
203
+
204
+ class Push
205
+ def self.push_class
206
+ (ENV["rio_push_class"] || "Juggernaut").constantize
207
+ end
208
+
209
+ def self.show_connected_clients
210
+ self.push_class.show_connected_clients
211
+ end
212
+
213
+ def self.show_clients_for_channel(channel)
214
+ self.push_class.show_clients_for_channel(channel)
215
+ end
216
+
217
+ def self.send_to_channel(data, channel)
218
+ self.push_class.send_to_channel(data, channel)
219
+ end
220
+
221
+ def self.send_to_clients(data, clients)
222
+ self.push_class.send_to_clients(data, clients)
223
+ end
224
+ end
225
+
226
+ module RioResource
227
+ def index
228
+ raise "Index operation not supported" unless self.class.rio_actions.include?(:index)
229
+
230
+ parsed_index_conditions = index_conditions
231
+
232
+ raise "Index operation not authorized" unless self.index_authorized?(parsed_index_conditions)
233
+
234
+ render :json => scope.find(:all, :conditions => parsed_index_conditions)
235
+ end
236
+
237
+ def index_conditions
238
+ ActiveSupport::JSON.decode(params[:conditions])
239
+ end
240
+
241
+ def show
242
+ raise "Show operation not supported" unless self.class.rio_actions.include?(:show)
243
+ raise "Show operation not authorized" unless self.show_authorized?(params[:id])
244
+
245
+ render :json => scope.find(params[:id])
246
+ end
247
+
248
+ def create
249
+ raise "Create operation not supported" unless self.class.rio_actions.include?(:create)
250
+
251
+ if (params["transaction"])
252
+ execute_transaction(params["transaction"], params["transaction_key"])
253
+ else
254
+ raise "Create operation not authorized" unless self.create_authorized?(params[model_param_name])
255
+ obj = create_scope.new(params[model_param_name])
256
+
257
+ valid = true
258
+ model.transaction do
259
+ if (obj.save)
260
+ objects = {}
261
+ objects[obj.id] = obj
262
+ unless (model.validate_transaction!({}, objects))
263
+ valid = false
264
+ raise ActiveRecord::Rollback
265
+ end
266
+ else
267
+ valid = false
268
+ raise ActiveRecord::Rollback
269
+ end
270
+ end
271
+
272
+ if (valid)
273
+ remote_create(obj, params["transaction_key"])
274
+ render :json => obj
275
+ else
276
+ render :json => obj.errors, :status => 500
277
+ end
278
+ end
279
+ end
280
+
281
+ def update
282
+ raise "Update operation not supported" unless self.class.rio_actions.include?(:update)
283
+ paranoid = scope.respond_to?(:find_with_deleted)
284
+ if (paranoid)
285
+ obj = scope.find_with_deleted(params[:id])
286
+ else
287
+ obj = scope.find(params[:id])
288
+ end
289
+
290
+ needs_recover = (paranoid and obj.deleted?)
291
+
292
+ valid = true
293
+ changed_fields = []
294
+ model.transaction do
295
+ if (needs_recover)
296
+ raise "Update operation not authorized" unless self.update_authorized?(obj, ["deleted_at"])
297
+ obj.recover!
298
+ end
299
+
300
+ obj.attributes = params[model_param_name]
301
+ changed_fields = obj.changed
302
+ raise "Update operation not authorized" unless self.update_authorized?(obj, changed_fields)
303
+ if (obj.save)
304
+ objects = {}
305
+ objects[obj.id] = obj
306
+ unless (model.validate_transaction!({}, objects))
307
+ valid = false
308
+ raise ActiveRecord::Rollback
309
+ end
310
+ else
311
+ valid = false
312
+ raise ActiveRecord::Rollback
313
+ end
314
+ end
315
+
316
+ if (valid)
317
+ if (needs_recover)
318
+ remote_create(obj, params["transaction_key"])
319
+ else
320
+ remote_update(obj, changed_fields, params["transaction_key"])
321
+ end
322
+ render :json => obj
323
+ else
324
+ render :json => obj.errors, :status => 500
325
+ end
326
+ end
327
+
328
+ def destroy
329
+ raise "Destroy operation not supported" unless self.class.rio_actions.include?(:destroy)
330
+ obj = scope.find(params[:id])
331
+ raise "Destroy operation not authorized" unless self.destroy_authorized?(obj)
332
+
333
+ valid = true
334
+ model.transaction do
335
+ if (obj.destroy)
336
+ objects = {}
337
+ objects[obj.id] = obj
338
+
339
+ unless (model.validate_transaction!({}, objects))
340
+ valid = false
341
+ raise ActiveRecord::Rollback
342
+ end
343
+ else
344
+ valid = false
345
+ raise ActiveRecord::Rollback
346
+ end
347
+ end
348
+
349
+ if (valid)
350
+ remote_destroy(obj, params["transaction_key"])
351
+ render :json => { :id => params[:id] }
352
+ else
353
+ render :json => obj.errors, :status => 500
354
+ end
355
+ end
356
+
357
+ protected
358
+
359
+ def scope
360
+ model
361
+ end
362
+
363
+ def create_scope
364
+ scope
365
+ end
366
+
367
+ def model
368
+ model_class_name = controller_class_name.match(/(.*)Controller$/)[1].singularize
369
+ model_class_name.constantize
370
+ end
371
+
372
+ def index_authorized?(params)
373
+ true
374
+ end
375
+
376
+ def show_authorized?(id)
377
+ true
378
+ end
379
+
380
+ def create_authorized?(params)
381
+ true
382
+ end
383
+
384
+ def update_authorized?(instance, attributes)
385
+ true
386
+ end
387
+
388
+ def destroy_authorized?(instance)
389
+ true
390
+ end
391
+
392
+
393
+
394
+ private
395
+
396
+ def execute_transaction(transaction, transaction_key)
397
+ valid = true
398
+ objects = {}
399
+ remote_transaction_data = []
400
+
401
+ # If any of these items aren't found the transaction is invalid and will fail.
402
+ # By verifying this here we can take for granted that some of these might be destroyed
403
+ # as part of an association or before/after filter and not be available when needed to be destroyed.
404
+ to_find = transaction.keys.select {|t| t.to_i > 0}
405
+ paranoid = scope.respond_to?(:find_with_deleted)
406
+ if (paranoid)
407
+ existing_entities = scope.find_with_deleted(to_find)
408
+ else
409
+ existing_entities = scope.find(to_find)
410
+ end
411
+ existing_entities = [existing_entities].flatten
412
+
413
+ model.transaction do
414
+ new_ids, existing_ids = transaction.keys.partition { |id| id.to_i < 0 }
415
+
416
+ transaction.keys.each do |id|
417
+ obj = existing_entities.detect { |e| e.id == id.to_i }
418
+
419
+ if (id.to_i < 0)
420
+ raise "Create operation not authorized" unless self.create_authorized?(transaction[id])
421
+ obj = create_scope.create(transaction[id])
422
+ remote_transaction_data.push({ :action => "create", :name => model.to_s, :id => obj.id, :json => obj })
423
+ elsif (paranoid and (not obj.nil?) and obj.deleted?)
424
+ obj.recover!
425
+ obj.attributes = transaction[id]
426
+ raise "Update operation not authorized" unless self.update_authorized?(obj, obj.changed)
427
+ obj.save
428
+ remote_transaction_data.push({ :action => "create", :name => model.to_s, :id => obj.id, :json => obj })
429
+ elsif (transaction[id] == "delete")
430
+ raise "Destroy operation not authorized" unless self.destroy_authorized?(obj)
431
+ obj.destroy
432
+ remote_transaction_data.push({ :action => "destroy", :name => model.to_s, :id => obj.id, :json => obj })
433
+ else
434
+ obj.attributes = transaction[id]
435
+ raise "Update operation not authorized" unless self.update_authorized?(obj, obj.changed)
436
+ json_fields = obj.changed
437
+ obj.save
438
+ remote_transaction_data.push({ :action => "update", :name => model.to_s, :id => obj.id, :obj => obj, :json_fields => json_fields })
439
+ end
440
+
441
+ if (!obj.valid?)
442
+ valid = false
443
+ end
444
+
445
+ objects[id] = obj
446
+ end
447
+
448
+ transaction.keys.each do |id|
449
+ if (transaction[id] != "delete")
450
+ (transaction[id].keys - ["id"]).each do |k|
451
+ if (new_ids.include?(transaction[id][k].to_s))
452
+ objects[id].update_attribute(k, objects[transaction[id][k].to_s].id)
453
+ end
454
+ end
455
+ end
456
+ end
457
+
458
+ unless (model.validate_transaction!(transaction, objects))
459
+ valid = false
460
+ raise ActiveRecord::Rollback
461
+ end
462
+
463
+ raise ActiveRecord::Rollback unless valid
464
+ end
465
+
466
+ if (valid)
467
+ remote_transaction(remote_transaction_data, transaction_key)
468
+ render :json => {
469
+ :transaction => objects.keys.inject({}) do |acc, id|
470
+ acc[id] = objects[id]
471
+ acc
472
+ end
473
+ }
474
+ else
475
+ render :json => {
476
+ :transaction => "FAILED"
477
+ }, :status => 500
478
+ end
479
+ end
480
+
481
+ def remote_create(obj, transaction_key)
482
+ if (Rio::Push and model.broadcast?)
483
+ begin
484
+ Rio::Push.send_to_clients("""
485
+ rio.Model.remoteCreate({
486
+ transactionKey: \"#{transaction_key}\",
487
+ name: \"#{ model.to_s }\",
488
+ id: \"#{ obj.id }\",
489
+ json: #{ obj.to_json }
490
+ });
491
+ """, other_client_ids(obj))
492
+ rescue
493
+ RAILS_DEFAULT_LOGGER.error("\n Failed to send a remote create \n")
494
+ end
495
+ end
496
+ end
497
+
498
+ def remote_update(obj, changed_fields, transaction_key)
499
+ if (Rio::Push and model.broadcast?)
500
+ begin
501
+
502
+ json = changed_fields.inject({}) do |acc, f|
503
+ acc[f] = obj.send(f)
504
+ acc
505
+ end
506
+
507
+ if (ActiveRecord::Base.include_root_in_json)
508
+ json = { "#{model.class_name.underscore}" => json }
509
+ end
510
+
511
+ Rio::Push.send_to_clients("""
512
+ rio.Model.remoteUpdate({
513
+ transactionKey: \"#{transaction_key}\",
514
+ name: \"#{ model.to_s }\",
515
+ id: \"#{ obj.id }\",
516
+ json: #{ json.to_json }
517
+ });
518
+ """, other_client_ids(obj))
519
+ rescue
520
+ RAILS_DEFAULT_LOGGER.error("\n Failed to send a remote update \n")
521
+ end
522
+ end
523
+ end
524
+
525
+ def remote_destroy(obj, transaction_key)
526
+ if(Rio::Push and model.broadcast?)
527
+ begin
528
+ Rio::Push.send_to_clients("""
529
+ rio.Model.remoteDestroy({
530
+ transactionKey: \"#{transaction_key}\",
531
+ name: \"#{ model.to_s }\",
532
+ id: \"#{ obj.id }\"
533
+ });
534
+ """, other_client_ids(obj))
535
+ rescue
536
+ RAILS_DEFAULT_LOGGER.error("\n Failed to send a remote destroy \n")
537
+ end
538
+ end
539
+ end
540
+
541
+ def remote_transaction(transaction, transaction_key)
542
+ if(Rio::Push and model.broadcast?)
543
+ begin
544
+ other_client_list = transaction.map {|t| other_client_ids(t[:obj] || t[:json]) }.inject { |acc, ids| acc & ids }
545
+
546
+ transaction.each do |t|
547
+ if (t[:obj])
548
+ obj = t.delete(:obj)
549
+ fields = t.delete(:json_fields)
550
+ t[:json] = fields.inject({}) do |acc, f|
551
+ acc[f] = obj.send(f)
552
+ acc
553
+ end
554
+
555
+ if (ActiveRecord::Base.include_root_in_json)
556
+ t[:json] = { "#{model.class_name.underscore}" => t[:json] }
557
+ end
558
+ end
559
+ end
560
+
561
+ Rio::Push.send_to_clients("""
562
+ rio.Model.remoteTransaction({
563
+ transactionKey: \"#{transaction_key}\",
564
+ transaction: #{transaction.to_json}
565
+ });
566
+ """, other_client_list)
567
+ rescue => e
568
+ RAILS_DEFAULT_LOGGER.error("\n Failed to send a remote transaction \n")
569
+ RAILS_DEFAULT_LOGGER.error(e)
570
+ end
571
+ end
572
+ end
573
+
574
+ def other_client_ids(instance)
575
+ if(model.broadcast_mode == :strict)
576
+ instance.broadcast_to
577
+ else
578
+ Rio::Push.show_connected_clients.map { |c| c["id"] || c["client_id"] }
579
+ end
580
+ end
581
+
582
+ def model_param_name
583
+ model.class_name.underscore
584
+ end
585
+ end
586
+ end