authorails 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (347) hide show
  1. data/AUTHORAILS_README +20 -0
  2. data/CHANGELOG +1366 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README +182 -0
  5. data/Rakefile +334 -0
  6. data/bin/about +3 -0
  7. data/bin/authorails +19 -0
  8. data/bin/breakpointer +3 -0
  9. data/bin/console +3 -0
  10. data/bin/destroy +3 -0
  11. data/bin/generate +3 -0
  12. data/bin/performance/benchmarker +3 -0
  13. data/bin/performance/profiler +3 -0
  14. data/bin/plugin +3 -0
  15. data/bin/process/inspector +3 -0
  16. data/bin/process/reaper +3 -0
  17. data/bin/process/spawner +3 -0
  18. data/bin/runner +3 -0
  19. data/bin/server +3 -0
  20. data/builtin/rails_info/rails/info.rb +123 -0
  21. data/builtin/rails_info/rails/info_controller.rb +9 -0
  22. data/builtin/rails_info/rails/info_helper.rb +2 -0
  23. data/builtin/rails_info/rails_info_controller.rb +2 -0
  24. data/configs/apache.conf +40 -0
  25. data/configs/databases/frontbase.yml +28 -0
  26. data/configs/databases/mysql.yml +48 -0
  27. data/configs/databases/oracle.yml +39 -0
  28. data/configs/databases/postgresql.yml +44 -0
  29. data/configs/databases/sqlite2.yml +16 -0
  30. data/configs/databases/sqlite3.yml +19 -0
  31. data/configs/empty.log +0 -0
  32. data/configs/lighttpd.conf +54 -0
  33. data/configs/routes.rb +23 -0
  34. data/controllers/accounts_controller.rb +11 -0
  35. data/controllers/admin_controller.rb +76 -0
  36. data/controllers/begin_controller.rb +5 -0
  37. data/controllers/login_controller.rb +101 -0
  38. data/controllers/permission_controller.rb +91 -0
  39. data/controllers/roles_controller.rb +58 -0
  40. data/controllers/tables_controller.rb +714 -0
  41. data/dispatches/dispatch.fcgi +24 -0
  42. data/dispatches/dispatch.rb +10 -0
  43. data/dispatches/gateway.cgi +97 -0
  44. data/doc/README_FOR_APP +2 -0
  45. data/environments/boot.rb +45 -0
  46. data/environments/development.rb +21 -0
  47. data/environments/environment.rb +63 -0
  48. data/environments/production.rb +18 -0
  49. data/environments/test.rb +19 -0
  50. data/fresh_rakefile +10 -0
  51. data/helpers/application.rb +607 -0
  52. data/helpers/application_helper.rb +315 -0
  53. data/helpers/permission_helper.rb +27 -0
  54. data/helpers/test_helper.rb +28 -0
  55. data/html/404.html +30 -0
  56. data/html/500.html +30 -0
  57. data/html/favicon.ico +0 -0
  58. data/html/images/ArrowDn.png +0 -0
  59. data/html/images/ArrowUp.png +0 -0
  60. data/html/images/arrow.gif +0 -0
  61. data/html/images/authorails_logo.gif +0 -0
  62. data/html/images/delete.png +0 -0
  63. data/html/images/edit.png +0 -0
  64. data/html/images/minus.gif +0 -0
  65. data/html/images/plus.gif +0 -0
  66. data/html/images/rails.png +0 -0
  67. data/html/images/show.png +0 -0
  68. data/html/images/spinner.gif +0 -0
  69. data/html/index.html +273 -0
  70. data/html/javascripts/application.js +2 -0
  71. data/html/javascripts/controls.js +833 -0
  72. data/html/javascripts/dragdrop.js +942 -0
  73. data/html/javascripts/effects.js +1088 -0
  74. data/html/javascripts/live_validation.js +4 -0
  75. data/html/javascripts/prototype.js +2515 -0
  76. data/html/robots.txt +1 -0
  77. data/lib/authorails/version.rb +9 -0
  78. data/lib/binding_of_caller.rb +85 -0
  79. data/lib/breakpoint.rb +553 -0
  80. data/lib/breakpoint_client.rb +196 -0
  81. data/lib/code_statistics.rb +107 -0
  82. data/lib/commands.rb +17 -0
  83. data/lib/commands/about.rb +2 -0
  84. data/lib/commands/breakpointer.rb +1 -0
  85. data/lib/commands/console.rb +25 -0
  86. data/lib/commands/destroy.rb +6 -0
  87. data/lib/commands/generate.rb +6 -0
  88. data/lib/commands/ncgi/listener +86 -0
  89. data/lib/commands/ncgi/tracker +69 -0
  90. data/lib/commands/performance/benchmarker.rb +24 -0
  91. data/lib/commands/performance/profiler.rb +50 -0
  92. data/lib/commands/plugin.rb +918 -0
  93. data/lib/commands/process/inspector.rb +68 -0
  94. data/lib/commands/process/reaper.rb +149 -0
  95. data/lib/commands/process/spawner.rb +209 -0
  96. data/lib/commands/process/spinner.rb +57 -0
  97. data/lib/commands/runner.rb +48 -0
  98. data/lib/commands/server.rb +39 -0
  99. data/lib/commands/servers/base.rb +19 -0
  100. data/lib/commands/servers/lighttpd.rb +94 -0
  101. data/lib/commands/servers/mongrel.rb +65 -0
  102. data/lib/commands/servers/webrick.rb +59 -0
  103. data/lib/commands/update.rb +4 -0
  104. data/lib/console_app.rb +27 -0
  105. data/lib/console_sandbox.rb +6 -0
  106. data/lib/console_with_helpers.rb +23 -0
  107. data/lib/dispatcher.rb +173 -0
  108. data/lib/fcgi_handler.rb +225 -0
  109. data/lib/initializer.rb +702 -0
  110. data/lib/rails_generator.rb +43 -0
  111. data/lib/rails_generator/base.rb +261 -0
  112. data/lib/rails_generator/commands.rb +581 -0
  113. data/lib/rails_generator/generated_attribute.rb +42 -0
  114. data/lib/rails_generator/generators/applications/app/USAGE +16 -0
  115. data/lib/rails_generator/generators/applications/app/app_generator.rb +341 -0
  116. data/lib/rails_generator/generators/components/controller/USAGE +30 -0
  117. data/lib/rails_generator/generators/components/controller/controller_generator.rb +37 -0
  118. data/lib/rails_generator/generators/components/controller/templates/controller.rb +10 -0
  119. data/lib/rails_generator/generators/components/controller/templates/functional_test.rb +18 -0
  120. data/lib/rails_generator/generators/components/controller/templates/helper.rb +2 -0
  121. data/lib/rails_generator/generators/components/controller/templates/view.rhtml +2 -0
  122. data/lib/rails_generator/generators/components/integration_test/USAGE +14 -0
  123. data/lib/rails_generator/generators/components/integration_test/integration_test_generator.rb +16 -0
  124. data/lib/rails_generator/generators/components/integration_test/templates/integration_test.rb +10 -0
  125. data/lib/rails_generator/generators/components/mailer/USAGE +18 -0
  126. data/lib/rails_generator/generators/components/mailer/mailer_generator.rb +34 -0
  127. data/lib/rails_generator/generators/components/mailer/templates/fixture.rhtml +3 -0
  128. data/lib/rails_generator/generators/components/mailer/templates/mailer.rb +13 -0
  129. data/lib/rails_generator/generators/components/mailer/templates/unit_test.rb +37 -0
  130. data/lib/rails_generator/generators/components/mailer/templates/view.rhtml +3 -0
  131. data/lib/rails_generator/generators/components/migration/USAGE +14 -0
  132. data/lib/rails_generator/generators/components/migration/migration_generator.rb +7 -0
  133. data/lib/rails_generator/generators/components/migration/templates/migration.rb +7 -0
  134. data/lib/rails_generator/generators/components/model/USAGE +26 -0
  135. data/lib/rails_generator/generators/components/model/model_generator.rb +38 -0
  136. data/lib/rails_generator/generators/components/model/templates/fixtures.yml +11 -0
  137. data/lib/rails_generator/generators/components/model/templates/migration.rb +13 -0
  138. data/lib/rails_generator/generators/components/model/templates/model.rb +2 -0
  139. data/lib/rails_generator/generators/components/model/templates/unit_test.rb +10 -0
  140. data/lib/rails_generator/generators/components/observer/USAGE +15 -0
  141. data/lib/rails_generator/generators/components/observer/observer_generator.rb +16 -0
  142. data/lib/rails_generator/generators/components/observer/templates/observer.rb +2 -0
  143. data/lib/rails_generator/generators/components/observer/templates/unit_test.rb +10 -0
  144. data/lib/rails_generator/generators/components/plugin/USAGE +35 -0
  145. data/lib/rails_generator/generators/components/plugin/plugin_generator.rb +38 -0
  146. data/lib/rails_generator/generators/components/plugin/templates/README +4 -0
  147. data/lib/rails_generator/generators/components/plugin/templates/Rakefile +22 -0
  148. data/lib/rails_generator/generators/components/plugin/templates/USAGE +8 -0
  149. data/lib/rails_generator/generators/components/plugin/templates/generator.rb +8 -0
  150. data/lib/rails_generator/generators/components/plugin/templates/init.rb +1 -0
  151. data/lib/rails_generator/generators/components/plugin/templates/install.rb +1 -0
  152. data/lib/rails_generator/generators/components/plugin/templates/plugin.rb +1 -0
  153. data/lib/rails_generator/generators/components/plugin/templates/tasks.rake +4 -0
  154. data/lib/rails_generator/generators/components/plugin/templates/uninstall.rb +1 -0
  155. data/lib/rails_generator/generators/components/plugin/templates/unit_test.rb +8 -0
  156. data/lib/rails_generator/generators/components/resource/resource_generator.rb +76 -0
  157. data/lib/rails_generator/generators/components/resource/templates/USAGE +18 -0
  158. data/lib/rails_generator/generators/components/resource/templates/controller.rb +2 -0
  159. data/lib/rails_generator/generators/components/resource/templates/fixtures.yml +11 -0
  160. data/lib/rails_generator/generators/components/resource/templates/functional_test.rb +20 -0
  161. data/lib/rails_generator/generators/components/resource/templates/helper.rb +2 -0
  162. data/lib/rails_generator/generators/components/resource/templates/migration.rb +13 -0
  163. data/lib/rails_generator/generators/components/resource/templates/model.rb +2 -0
  164. data/lib/rails_generator/generators/components/resource/templates/unit_test.rb +10 -0
  165. data/lib/rails_generator/generators/components/scaffold/USAGE +32 -0
  166. data/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb +208 -0
  167. data/lib/rails_generator/generators/components/scaffold/templates/controller.rb +134 -0
  168. data/lib/rails_generator/generators/components/scaffold/templates/form.rhtml +3 -0
  169. data/lib/rails_generator/generators/components/scaffold/templates/form_scaffolding.rhtml +35 -0
  170. data/lib/rails_generator/generators/components/scaffold/templates/functional_test.rb +102 -0
  171. data/lib/rails_generator/generators/components/scaffold/templates/helper.rb +2 -0
  172. data/lib/rails_generator/generators/components/scaffold/templates/layout.rhtml +17 -0
  173. data/lib/rails_generator/generators/components/scaffold/templates/partial_list_elements.rhtml +127 -0
  174. data/lib/rails_generator/generators/components/scaffold/templates/style.css +74 -0
  175. data/lib/rails_generator/generators/components/scaffold/templates/view_edit.rhtml +75 -0
  176. data/lib/rails_generator/generators/components/scaffold/templates/view_list.rhtml +30 -0
  177. data/lib/rails_generator/generators/components/scaffold/templates/view_new.rhtml +8 -0
  178. data/lib/rails_generator/generators/components/scaffold/templates/view_show.rhtml +37 -0
  179. data/lib/rails_generator/generators/components/scaffold_resource/USAGE +29 -0
  180. data/lib/rails_generator/generators/components/scaffold_resource/scaffold_resource_generator.rb +92 -0
  181. data/lib/rails_generator/generators/components/scaffold_resource/templates/controller.rb +79 -0
  182. data/lib/rails_generator/generators/components/scaffold_resource/templates/fixtures.yml +11 -0
  183. data/lib/rails_generator/generators/components/scaffold_resource/templates/functional_test.rb +57 -0
  184. data/lib/rails_generator/generators/components/scaffold_resource/templates/helper.rb +2 -0
  185. data/lib/rails_generator/generators/components/scaffold_resource/templates/layout.rhtml +17 -0
  186. data/lib/rails_generator/generators/components/scaffold_resource/templates/migration.rb +13 -0
  187. data/lib/rails_generator/generators/components/scaffold_resource/templates/model.rb +2 -0
  188. data/lib/rails_generator/generators/components/scaffold_resource/templates/style.css +74 -0
  189. data/lib/rails_generator/generators/components/scaffold_resource/templates/unit_test.rb +10 -0
  190. data/lib/rails_generator/generators/components/scaffold_resource/templates/view_edit.rhtml +19 -0
  191. data/lib/rails_generator/generators/components/scaffold_resource/templates/view_index.rhtml +24 -0
  192. data/lib/rails_generator/generators/components/scaffold_resource/templates/view_new.rhtml +18 -0
  193. data/lib/rails_generator/generators/components/scaffold_resource/templates/view_show.rhtml +10 -0
  194. data/lib/rails_generator/generators/components/session_migration/USAGE +15 -0
  195. data/lib/rails_generator/generators/components/session_migration/session_migration_generator.rb +18 -0
  196. data/lib/rails_generator/generators/components/session_migration/templates/migration.rb +16 -0
  197. data/lib/rails_generator/generators/components/web_service/USAGE +28 -0
  198. data/lib/rails_generator/generators/components/web_service/templates/api_definition.rb +5 -0
  199. data/lib/rails_generator/generators/components/web_service/templates/controller.rb +8 -0
  200. data/lib/rails_generator/generators/components/web_service/templates/functional_test.rb +19 -0
  201. data/lib/rails_generator/generators/components/web_service/web_service_generator.rb +29 -0
  202. data/lib/rails_generator/lookup.rb +209 -0
  203. data/lib/rails_generator/manifest.rb +53 -0
  204. data/lib/rails_generator/options.rb +143 -0
  205. data/lib/rails_generator/scripts.rb +83 -0
  206. data/lib/rails_generator/scripts/destroy.rb +7 -0
  207. data/lib/rails_generator/scripts/generate.rb +7 -0
  208. data/lib/rails_generator/scripts/update.rb +12 -0
  209. data/lib/rails_generator/simple_logger.rb +46 -0
  210. data/lib/rails_generator/spec.rb +44 -0
  211. data/lib/railties_path.rb +1 -0
  212. data/lib/ruby_version_check.rb +17 -0
  213. data/lib/rubyprof_ext.rb +35 -0
  214. data/lib/tasks/databases.rake +187 -0
  215. data/lib/tasks/documentation.rake +82 -0
  216. data/lib/tasks/framework.rake +112 -0
  217. data/lib/tasks/log.rake +9 -0
  218. data/lib/tasks/misc.rake +4 -0
  219. data/lib/tasks/pre_namespace_aliases.rake +53 -0
  220. data/lib/tasks/rails.rb +8 -0
  221. data/lib/tasks/statistics.rake +18 -0
  222. data/lib/tasks/testing.rake +120 -0
  223. data/lib/tasks/tmp.rake +37 -0
  224. data/lib/test_help.rb +19 -0
  225. data/lib/webrick_server.rb +166 -0
  226. data/libs/migration_helper.rb +11 -0
  227. data/migrations/001_create_logins.rb +22 -0
  228. data/migrations/002_create_admins.rb +16 -0
  229. data/migrations/003_create_roles.rb +13 -0
  230. data/migrations/004_create_tables.rb +11 -0
  231. data/migrations/005_create_attr_types.rb +13 -0
  232. data/migrations/006_create_table_fields.rb +22 -0
  233. data/migrations/007_create_tab_operations.rb +13 -0
  234. data/migrations/008_create_attr_operations.rb +13 -0
  235. data/migrations/009_create_tab_permissions.rb +21 -0
  236. data/migrations/010_create_attr_permissions.rb +21 -0
  237. data/migrations/011_create_relations.rb +23 -0
  238. data/migrations/012_create_scaffolds.rb +11 -0
  239. data/migrations/013_create_relation_permissions.rb +20 -0
  240. data/models/admin.rb +38 -0
  241. data/models/attr_operation.rb +3 -0
  242. data/models/attr_permission.rb +5 -0
  243. data/models/attr_type.rb +3 -0
  244. data/models/login.rb +51 -0
  245. data/models/relation.rb +5 -0
  246. data/models/relation_permission.rb +4 -0
  247. data/models/role.rb +13 -0
  248. data/models/scaffold.rb +2 -0
  249. data/models/tab_operation.rb +3 -0
  250. data/models/tab_permission.rb +5 -0
  251. data/models/table.rb +18 -0
  252. data/models/table_field.rb +6 -0
  253. data/plugins/redhillonrails_core/CHANGELOG +186 -0
  254. data/plugins/redhillonrails_core/MIT-LICENSE +20 -0
  255. data/plugins/redhillonrails_core/README +152 -0
  256. data/plugins/redhillonrails_core/init.rb +1 -0
  257. data/plugins/redhillonrails_core/lib/red_hill_consulting/core/active_record/base.rb +54 -0
  258. data/plugins/redhillonrails_core/lib/red_hill_consulting/core/active_record/connection_adapters/abstract_adapter.rb +46 -0
  259. data/plugins/redhillonrails_core/lib/red_hill_consulting/core/active_record/connection_adapters/column.rb +21 -0
  260. data/plugins/redhillonrails_core/lib/red_hill_consulting/core/active_record/connection_adapters/foreign_key_definition.rb +26 -0
  261. data/plugins/redhillonrails_core/lib/red_hill_consulting/core/active_record/connection_adapters/index_definition.rb +11 -0
  262. data/plugins/redhillonrails_core/lib/red_hill_consulting/core/active_record/connection_adapters/mysql_adapter.rb +94 -0
  263. data/plugins/redhillonrails_core/lib/red_hill_consulting/core/active_record/connection_adapters/mysql_column.rb +8 -0
  264. data/plugins/redhillonrails_core/lib/red_hill_consulting/core/active_record/connection_adapters/postgresql_adapter.rb +131 -0
  265. data/plugins/redhillonrails_core/lib/red_hill_consulting/core/active_record/connection_adapters/schema_statements.rb +23 -0
  266. data/plugins/redhillonrails_core/lib/red_hill_consulting/core/active_record/connection_adapters/sqlite3_adapter.rb +9 -0
  267. data/plugins/redhillonrails_core/lib/red_hill_consulting/core/active_record/connection_adapters/table_definition.rb +27 -0
  268. data/plugins/redhillonrails_core/lib/red_hill_consulting/core/active_record/schema.rb +25 -0
  269. data/plugins/redhillonrails_core/lib/red_hill_consulting/core/active_record/schema_dumper.rb +58 -0
  270. data/plugins/redhillonrails_core/lib/redhillonrails_core.rb +19 -0
  271. data/plugins/redhillonrails_core/tasks/db/comments.rake +9 -0
  272. data/plugins/schema_validations/CHANGELOG +149 -0
  273. data/plugins/schema_validations/MIT-LICENSE +20 -0
  274. data/plugins/schema_validations/README +54 -0
  275. data/plugins/schema_validations/about.yml +5 -0
  276. data/plugins/schema_validations/init.rb +1 -0
  277. data/plugins/schema_validations/install.rb +1 -0
  278. data/plugins/schema_validations/lib/red_hill_consulting/schema_validations/active_record/base.rb +108 -0
  279. data/plugins/schema_validations/lib/schema_validations.rb +1 -0
  280. data/plugins/svn/README +69 -0
  281. data/plugins/svn/Rakefile +22 -0
  282. data/plugins/svn/assets/javascripts/live_validation.js +4 -0
  283. data/plugins/svn/assets/stylesheets/live_validation.css +28 -0
  284. data/plugins/svn/init.rb +2 -0
  285. data/plugins/svn/install.rb +1 -0
  286. data/plugins/svn/lib/form_helpers.rb +49 -0
  287. data/plugins/svn/lib/live_validations.rb +73 -0
  288. data/plugins/svn/tasks/live_validation_tasks.rake +17 -0
  289. data/plugins/svn/test/form_helpers_test.rb +214 -0
  290. data/plugins/svn/test/live_validations_test.rb +124 -0
  291. data/plugins/svn/test/resource.rb +17 -0
  292. data/plugins/svn/uninstall.rb +1 -0
  293. data/stylesheets/live_validation.css +28 -0
  294. data/stylesheets/print.css +72 -0
  295. data/stylesheets/scaffold.css +175 -0
  296. data/views/accounts/index.rhtml +12 -0
  297. data/views/accounts/show.rhtml +5 -0
  298. data/views/admin/_form.rhtml +15 -0
  299. data/views/admin/add_user.rhtml +21 -0
  300. data/views/admin/change_pwd.rhtml +23 -0
  301. data/views/admin/edit_user.rhtml +12 -0
  302. data/views/admin/index.rhtml +19 -0
  303. data/views/begin/index.rhtml +0 -0
  304. data/views/layouts/general.rhtml +59 -0
  305. data/views/layouts/login.rhtml +18 -0
  306. data/views/login/change_pwd.rhtml +21 -0
  307. data/views/login/expired_pwd.rhtml +19 -0
  308. data/views/login/index.rhtml +15 -0
  309. data/views/permission/index.rhtml +17 -0
  310. data/views/permission/relations.rhtml +28 -0
  311. data/views/permission/roles.rhtml +45 -0
  312. data/views/permission/tables.rhtml +53 -0
  313. data/views/roles/_form.rhtml +8 -0
  314. data/views/roles/edit.rhtml +11 -0
  315. data/views/roles/list.rhtml +28 -0
  316. data/views/roles/new.rhtml +8 -0
  317. data/views/roles/show.rhtml +14 -0
  318. data/views/shared_views/_advanced_search.rhtml +35 -0
  319. data/views/shared_views/_child_elements.rhtml +30 -0
  320. data/views/shared_views/_childs.rhtml +20 -0
  321. data/views/shared_views/_father_elements.rhtml +27 -0
  322. data/views/shared_views/_fathers.rhtml +21 -0
  323. data/views/shared_views/_fathers_header.rhtml +58 -0
  324. data/views/shared_views/_many_to_many_elements.rhtml +50 -0
  325. data/views/shared_views/_many_to_manys.rhtml +18 -0
  326. data/views/shared_views/_one_to_one_elements.rhtml +24 -0
  327. data/views/shared_views/_one_to_one_father_elements.rhtml +26 -0
  328. data/views/shared_views/_one_to_ones.rhtml +42 -0
  329. data/views/shared_views/_one_to_ones_header.rhtml +117 -0
  330. data/views/shared_views/edit_child.rhtml +89 -0
  331. data/views/shared_views/edit_many.rhtml +75 -0
  332. data/views/tables/_cascade.rhtml +10 -0
  333. data/views/tables/_field.rhtml +10 -0
  334. data/views/tables/_fk.rhtml +9 -0
  335. data/views/tables/_form.rhtml +9 -0
  336. data/views/tables/_join_table_name.rhtml +16 -0
  337. data/views/tables/_relation_types.rhtml +5 -0
  338. data/views/tables/_tables.rhtml +15 -0
  339. data/views/tables/attributes.rhtml +15 -0
  340. data/views/tables/edit.rhtml +11 -0
  341. data/views/tables/edit_field.rhtml +18 -0
  342. data/views/tables/list.rhtml +39 -0
  343. data/views/tables/new.rhtml +8 -0
  344. data/views/tables/new_field.rhtml +25 -0
  345. data/views/tables/relations.rhtml +24 -0
  346. data/views/tables/show.rhtml +24 -0
  347. metadata +518 -0
@@ -0,0 +1 @@
1
+ ActiveRecord::Base.send(:include, RedHillConsulting::SchemaValidations::ActiveRecord::Base)
@@ -0,0 +1,69 @@
1
+ LiveValidation is a plugin which allows automatic integration of your Rails application with Javascript library LiveValidation[http://www.livevalidation.com/]. This library implements client-side form validation and you can see a demo in its site.
2
+
3
+ This plugin generates the needed Javascript code to run client-side the validations you have already defined in your models (with Rails validation helpers) to run them server-side, and redefines form helpers to automaticaly include that Javascript code. You have not to write your validations twice so you can keep DRY. And if you have 1) used Rails validation helpers to validate your models, and 2) used Rails form helpers to create your forms, you only have to install this plugin to get your forms validated both server and client-side!
4
+
5
+ [Spanish[http://www.lacoctelera.com/porras/post/2007/10/12/plugin-livevalidation-rails]]
6
+
7
+ == A little HOWTO
8
+
9
+ 1. Install the plugin:
10
+
11
+ $ script/plugin install svn://rubyforge.org/var/svn/livevalidation
12
+
13
+ 2. Install Javascript and CSS files under public/, with this Rake task:
14
+
15
+ $ rake livevalidation:install
16
+
17
+ Remember including them in your headers, including Prototype too (as LiveValidation depends on it), this way (for example):
18
+
19
+ <%= javascript_include_tag 'prototype', 'live_validation' %>
20
+ <%= stylesheet_link_tag 'live_validation' %>
21
+
22
+ 3. There is no step 3 ;) You only need to add validations to your models, and crete your forms using the Rails form helpers, something like this:
23
+
24
+ <% form_for(:resource, :url => resources_path) do |f| %>
25
+ <%= f.text_field :name %>
26
+ [etc ...]
27
+ <% end %>
28
+
29
+ You can disable live validation for a given field using <tt>:live => false</tt>:
30
+
31
+ <%= f.text_field :name, :live => false %>
32
+
33
+ You can also reverse this schema so the default is <b>no validation</b>, including this in your <tt>config/environment.rb</tt>:
34
+
35
+ ActionView::live_validations = false
36
+
37
+ and enabling it only for some fields:
38
+
39
+ <%= f.text_field :name, :live => true %>
40
+
41
+ == Supported validations
42
+
43
+ * <tt>validates_presence_of</tt>
44
+ * <tt>validates_numericallity_of</tt>
45
+ * <tt>validates_format_of</tt>
46
+ * <tt>validates_length_of</tt>
47
+ * <tt>validates_confirmation_of</tt>
48
+
49
+ == Supported form helpers
50
+
51
+ * <tt>text_field</tt>
52
+ * <tt>text_area</tt>
53
+ * <tt>password_field</tt>
54
+
55
+ == Author
56
+
57
+ Plugin written by {Sergio Gil}[http://www.lacoctelera.com/porras]. Mail me to <tt>sgilperez at gmail.com</tt> for bug reports, feature requests or any comment.
58
+
59
+ == License
60
+
61
+ LiveValidation is licensed under the terms of the {MIT License}[http://www.opensource.org/licenses/mit-license.php].
62
+
63
+ Copyright (c) 2007 Sergio Gil
64
+
65
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
66
+
67
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
68
+
69
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,22 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the live_validation plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.pattern = 'test/**/*_test.rb'
12
+ t.verbose = true
13
+ end
14
+
15
+ desc 'Generate documentation for the live_validation plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'LiveValidation'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
@@ -0,0 +1,4 @@
1
+ // LiveValidation 1.3 (prototype.js version)
2
+ // Copyright (c) 2007-2008 Alec Hill (www.livevalidation.com)
3
+ // LiveValidation is licensed under the terms of the MIT License
4
+ var LiveValidation=Class.create();Object.extend(LiveValidation,{VERSION:"1.3 prototype",TEXTAREA:1,TEXT:2,PASSWORD:3,CHECKBOX:4,SELECT:5,FILE:6,massValidate:function(C){var D=true;for(var B=0,A=C.length;B<A;++B){var E=C[B].validate();if(D){D=E;}}return D;}});LiveValidation.prototype={validClass:"LV_valid",invalidClass:"LV_invalid",messageClass:"LV_validation_message",validFieldClass:"LV_valid_field",invalidFieldClass:"LV_invalid_field",initialize:function(B,A){if(!B){throw new Error("LiveValidation::initialize - No element reference or element id has been provided!");}this.element=$(B);if(!this.element){throw new Error("LiveValidation::initialize - No element with reference or id of '"+B+"' exists!");}this.elementType=this.getElementType();this.validations=[];this.form=this.element.form;this.options=Object.extend({validMessage:"OK",onValid:function(){this.insertMessage(this.createMessageSpan());this.addFieldClass();},onInvalid:function(){this.insertMessage(this.createMessageSpan());this.addFieldClass();},insertAfterWhatNode:this.element,onlyOnBlur:false,wait:0,onlyOnSubmit:false},A||{});var C=this.options.insertAfterWhatNode||this.element;this.options.insertAfterWhatNode=$(C);Object.extend(this,this.options);if(this.form){this.formObj=LiveValidationForm.getInstance(this.form);this.formObj.addField(this);}this.boundFocus=this.doOnFocus.bindAsEventListener(this);Event.observe(this.element,"focus",this.boundFocus);if(!this.onlyOnSubmit){switch(this.elementType){case LiveValidation.CHECKBOX:this.boundClick=this.validate.bindAsEventListener(this);Event.observe(this.element,"click",this.boundClick);case LiveValidation.SELECT:case LiveValidation.FILE:this.boundChange=this.validate.bindAsEventListener(this);Event.observe(this.element,"change",this.boundChange);break;default:if(!this.onlyOnBlur){this.boundKeyup=this.deferValidation.bindAsEventListener(this);Event.observe(this.element,"keyup",this.boundKeyup);}this.boundBlur=this.validate.bindAsEventListener(this);Event.observe(this.element,"blur",this.boundBlur);}}},destroy:function(){if(this.formObj){this.formObj.removeField(this);this.formObj.destroy();}Event.stopObserving(this.element,"focus",this.boundFocus);if(!this.onlyOnSubmit){switch(this.elementType){case LiveValidation.CHECKBOX:Event.stopObserving(this.element,"click",this.boundClick);case LiveValidation.SELECT:case LiveValidation.FILE:Event.stopObserving(this.element,"change",this.boundChange);break;default:if(!this.onlyOnBlur){Event.stopObserving(this.element,"keyup",this.boundKeyup);}Event.stopObserving(this.element,"blur",this.boundBlur);}}this.validations=[];this.removeMessageAndFieldClass();},add:function(A,B){this.validations.push({type:A,params:B||{}});return this;},remove:function(A,B){this.validations=this.validations.reject(function(C){return(C.type==A&&C.params==B);});return this;},deferValidation:function(A){if(this.wait>=300){this.removeMessageAndFieldClass();}if(this.timeout){clearTimeout(this.timeout);}this.timeout=setTimeout(this.validate.bind(this),this.wait);},doOnBlur:function(){this.focused=false;this.validate();},doOnFocus:function(){this.focused=true;this.removeMessageAndFieldClass();},getElementType:function(){switch(true){case (this.element.nodeName.toUpperCase()=="TEXTAREA"):return LiveValidation.TEXTAREA;case (this.element.nodeName.toUpperCase()=="INPUT"&&this.element.type.toUpperCase()=="TEXT"):return LiveValidation.TEXT;case (this.element.nodeName.toUpperCase()=="INPUT"&&this.element.type.toUpperCase()=="PASSWORD"):return LiveValidation.PASSWORD;case (this.element.nodeName.toUpperCase()=="INPUT"&&this.element.type.toUpperCase()=="CHECKBOX"):return LiveValidation.CHECKBOX;case (this.element.nodeName.toUpperCase()=="INPUT"&&this.element.type.toUpperCase()=="FILE"):return LiveValidation.FILE;case (this.element.nodeName.toUpperCase()=="SELECT"):return LiveValidation.SELECT;case (this.element.nodeName.toUpperCase()=="INPUT"):throw new Error("LiveValidation::getElementType - Cannot use LiveValidation on an "+this.element.type+" input!");default:throw new Error("LiveValidation::getElementType - Element must be an input, select, or textarea!");}},doValidations:function(){this.validationFailed=false;for(var C=0,A=this.validations.length;C<A;++C){var B=this.validations[C];switch(B.type){case Validate.Presence:case Validate.Confirmation:case Validate.Acceptance:this.displayMessageWhenEmpty=true;this.validationFailed=!this.validateElement(B.type,B.params);break;default:this.validationFailed=!this.validateElement(B.type,B.params);break;}if(this.validationFailed){return false;}}this.message=this.validMessage;return true;},validateElement:function(A,C){var D=(this.elementType==LiveValidation.SELECT)?this.element.options[this.element.selectedIndex].value:this.element.value;if(A==Validate.Acceptance){if(this.elementType!=LiveValidation.CHECKBOX){throw new Error("LiveValidation::validateElement - Element to validate acceptance must be a checkbox!");}D=this.element.checked;}var E=true;try{A(D,C);}catch(B){if(B instanceof Validate.Error){if(D!==""||(D===""&&this.displayMessageWhenEmpty)){this.validationFailed=true;this.message=B.message;E=false;}}else{throw B;}}finally{return E;}},validate:function(){if(!this.element.disabled){var A=this.doValidations();if(A){this.onValid();return true;}else{this.onInvalid();return false;}}else{return true;}},enable:function(){this.element.disabled=false;return this;},disable:function(){this.element.disabled=true;this.removeMessageAndFieldClass();return this;},createMessageSpan:function(){var A=document.createElement("span");var B=document.createTextNode(this.message);A.appendChild(B);return A;},insertMessage:function(B){this.removeMessage();var A=this.validationFailed?this.invalidClass:this.validClass;if((this.displayMessageWhenEmpty&&(this.elementType==LiveValidation.CHECKBOX||this.element.value==""))||this.element.value!=""){$(B).addClassName(this.messageClass+(" "+A));if(nxtSibling=this.insertAfterWhatNode.nextSibling){this.insertAfterWhatNode.parentNode.insertBefore(B,nxtSibling);}else{this.insertAfterWhatNode.parentNode.appendChild(B);}}},addFieldClass:function(){this.removeFieldClass();if(!this.validationFailed){if(this.displayMessageWhenEmpty||this.element.value!=""){if(!this.element.hasClassName(this.validFieldClass)){this.element.addClassName(this.validFieldClass);}}}else{if(!this.element.hasClassName(this.invalidFieldClass)){this.element.addClassName(this.invalidFieldClass);}}},removeMessage:function(){if(nxtEl=this.insertAfterWhatNode.next("."+this.messageClass)){nxtEl.remove();}},removeFieldClass:function(){this.element.removeClassName(this.invalidFieldClass);this.element.removeClassName(this.validFieldClass);},removeMessageAndFieldClass:function(){this.removeMessage();this.removeFieldClass();}};var LiveValidationForm=Class.create();Object.extend(LiveValidationForm,{instances:{},getInstance:function(A){var B=Math.random()*Math.random();if(!A.id){A.id="formId_"+B.toString().replace(/\./,"")+new Date().valueOf();}if(!LiveValidationForm.instances[A.id]){LiveValidationForm.instances[A.id]=new LiveValidationForm(A);}return LiveValidationForm.instances[A.id];}});LiveValidationForm.prototype={initialize:function(A){this.element=$(A);this.fields=[];this.oldOnSubmit=this.element.onsubmit||function(){};this.element.onsubmit=function(C){var B=(LiveValidation.massValidate(this.fields))?this.oldOnSubmit.call(this.element,C)!==false:false;if(!B){Event.stop(C);}}.bindAsEventListener(this);},addField:function(A){this.fields.push(A);},removeField:function(A){this.fields=this.fields.without(A);},destroy:function(A){if(this.fields.length!=0&&!A){return false;}this.element.onsubmit=this.oldOnSubmit;LiveValidationForm.instances[this.element.id]=null;return true;}};var Validate={Presence:function(A,B){var C=Object.extend({failureMessage:"Can't be empty!"},B||{});if(A===""||A===null||A===undefined){Validate.fail(C.failureMessage);}return true;},Numericality:function(B,C){var A=B;var B=Number(B);var C=C||{};var D={notANumberMessage:C.notANumberMessage||"Must be a number!",notAnIntegerMessage:C.notAnIntegerMessage||"Must be an integer!",wrongNumberMessage:C.wrongNumberMessage||"Must be "+C.is+"!",tooLowMessage:C.tooLowMessage||"Must not be less than "+C.minimum+"!",tooHighMessage:C.tooHighMessage||"Must not be more than "+C.maximum+"!",is:((C.is)||(C.is==0))?C.is:null,minimum:((C.minimum)||(C.minimum==0))?C.minimum:null,maximum:((C.maximum)||(C.maximum==0))?C.maximum:null,onlyInteger:C.onlyInteger||false};if(!isFinite(B)){Validate.fail(D.notANumberMessage);}if(D.onlyInteger&&((/\.0+$|\.$/.test(String(A)))||(B!=parseInt(B)))){Validate.fail(D.notAnIntegerMessage);}switch(true){case (D.is!==null):if(B!=Number(D.is)){Validate.fail(D.wrongNumberMessage);}break;case (D.minimum!==null&&D.maximum!==null):Validate.Numericality(B,{tooLowMessage:D.tooLowMessage,minimum:D.minimum});Validate.Numericality(B,{tooHighMessage:D.tooHighMessage,maximum:D.maximum});break;case (D.minimum!==null):if(B<Number(D.minimum)){Validate.fail(D.tooLowMessage);}break;case (D.maximum!==null):if(B>Number(D.maximum)){Validate.fail(D.tooHighMessage);}break;}return true;},Format:function(A,B){var A=String(A);var C=Object.extend({failureMessage:"Not valid!",pattern:/./,negate:false},B||{});if(!C.negate&&!C.pattern.test(A)){Validate.fail(C.failureMessage);}if(C.negate&&C.pattern.test(A)){Validate.fail(C.failureMessage);}return true;},Email:function(A,B){var C=Object.extend({failureMessage:"Must be a valid email address!"},B||{});Validate.Format(A,{failureMessage:C.failureMessage,pattern:/^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i});return true;},Length:function(A,B){var A=String(A);var B=B||{};var C={wrongLengthMessage:B.wrongLengthMessage||"Must be "+B.is+" characters long!",tooShortMessage:B.tooShortMessage||"Must not be less than "+B.minimum+" characters long!",tooLongMessage:B.tooLongMessage||"Must not be more than "+B.maximum+" characters long!",is:((B.is)||(B.is==0))?B.is:null,minimum:((B.minimum)||(B.minimum==0))?B.minimum:null,maximum:((B.maximum)||(B.maximum==0))?B.maximum:null};switch(true){case (C.is!==null):if(A.length!=Number(C.is)){Validate.fail(C.wrongLengthMessage);}break;case (C.minimum!==null&&C.maximum!==null):Validate.Length(A,{tooShortMessage:C.tooShortMessage,minimum:C.minimum});Validate.Length(A,{tooLongMessage:C.tooLongMessage,maximum:C.maximum});break;case (C.minimum!==null):if(A.length<Number(C.minimum)){Validate.fail(C.tooShortMessage);}break;case (C.maximum!==null):if(A.length>Number(C.maximum)){Validate.fail(C.tooLongMessage);}break;default:throw new Error("Validate::Length - Length(s) to validate against must be provided!");}return true;},Inclusion:function(C,D){var E=Object.extend({failureMessage:"Must be included in the list!",within:[],allowNull:false,partialMatch:false,caseSensitive:true,negate:false},D||{});if(E.allowNull&&C==null){return true;}if(!E.allowNull&&C==null){Validate.fail(E.failureMessage);}if(!E.caseSensitive){var A=[];E.within.each(function(F){if(typeof F=="string"){F=F.toLowerCase();}A.push(F);});E.within=A;if(typeof C=="string"){C=C.toLowerCase();}}var B=(E.within.indexOf(C)==-1)?false:true;if(E.partialMatch){B=false;E.within.each(function(F){if(C.indexOf(F)!=-1){B=true;}});}if((!E.negate&&!B)||(E.negate&&B)){Validate.fail(E.failureMessage);}return true;},Exclusion:function(A,B){var C=Object.extend({failureMessage:"Must not be included in the list!",within:[],allowNull:false,partialMatch:false,caseSensitive:true},B||{});C.negate=true;Validate.Inclusion(A,C);return true;},Confirmation:function(A,B){if(!B.match){throw new Error("Validate::Confirmation - Error validating confirmation: Id of element to match must be provided!");}var C=Object.extend({failureMessage:"Does not match!",match:null},B||{});C.match=$(B.match);if(!C.match){throw new Error("Validate::Confirmation - There is no reference with name of, or element with id of '"+C.match+"'!");}if(A!=C.match.value){Validate.fail(C.failureMessage);}return true;},Acceptance:function(A,B){var C=Object.extend({failureMessage:"Must be accepted!"},B||{});if(!A){Validate.fail(C.failureMessage);}return true;},Custom:function(A,B){var C=Object.extend({against:function(){return true;},args:{},failureMessage:"Not valid!"},B||{});if(!C.against(A,C.args)){Validate.fail(C.failureMessage);}return true;},now:function(A,D,C){if(!A){throw new Error("Validate::now - Validation function must be provided!");}var E=true;try{A(D,C||{});}catch(B){if(B instanceof Validate.Error){E=false;}else{throw B;}}finally{return E;}},Error:function(A){this.message=A;this.name="ValidationError";},fail:function(A){throw new Validate.Error(A);}};
@@ -0,0 +1,28 @@
1
+ .LV_validation_message{
2
+ font-weight:bold;
3
+ margin:0 0 0 5px;
4
+ }
5
+
6
+ .LV_valid {
7
+ color:#00CC00;
8
+ }
9
+
10
+ .LV_invalid {
11
+ color:#CC0000;
12
+ }
13
+
14
+ .LV_valid_field,
15
+ input.LV_valid_field:hover,
16
+ input.LV_valid_field:active,
17
+ textarea.LV_valid_field:hover,
18
+ textarea.LV_valid_field:active {
19
+ border: 1px solid #00CC00;
20
+ }
21
+
22
+ .LV_invalid_field,
23
+ input.LV_invalid_field:hover,
24
+ input.LV_invalid_field:active,
25
+ textarea.LV_invalid_field:hover,
26
+ textarea.LV_invalid_field:active {
27
+ border: 1px solid #CC0000;
28
+ }
@@ -0,0 +1,2 @@
1
+ require 'live_validations'
2
+ require 'form_helpers'
@@ -0,0 +1 @@
1
+ # Install hook code here
@@ -0,0 +1,49 @@
1
+ module ActionView
2
+
3
+ mattr_accessor :live_validations
4
+ ActionView::live_validations = true
5
+
6
+ module Helpers
7
+ module FormHelper
8
+ [ :text_field, :text_area, :password_field ].each do |field_type|
9
+ define_method "#{field_type}_with_live_validations" do |object_name, method, options|
10
+ live = options.delete(:live)
11
+ live = ActionView::live_validations if live.nil?
12
+ send("#{field_type}_without_live_validations", object_name, method, options) +
13
+ ( live ? live_validations_for(object_name, method) : '' )
14
+ end
15
+ alias_method_chain field_type, :live_validations
16
+ end
17
+
18
+ def live_validations_for(object_name, method)
19
+ script_tags(live_validation(object_name, method))
20
+ end
21
+
22
+ private
23
+
24
+ def live_validation(object_name, method)
25
+ if validations = self.instance_variable_get("@#{object_name.to_s}").class.live_validations[method.to_sym] rescue false
26
+ field_name = "#{object_name}_#{method}"
27
+ initialize_validator(field_name) +
28
+ validations.map do |type, configuration|
29
+ live_validation_code(field_name, type, configuration)
30
+ end.join(';')
31
+ else
32
+ ''
33
+ end
34
+ end
35
+
36
+ def initialize_validator(field_name)
37
+ "var #{field_name} = new LiveValidation('#{field_name}');"
38
+ end
39
+
40
+ def live_validation_code(field_name, type, configuration)
41
+ "#{field_name}.add(#{ActiveRecord::Validations::VALIDATION_METHODS[type]}" + ( configuration ? ", #{configuration.to_json}" : '') + ')'
42
+ end
43
+
44
+ def script_tags(js_code = '')
45
+ ( js_code.blank? ? '' : "<script>#{js_code}</script>" )
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,73 @@
1
+ module ActiveRecord
2
+ module Validations
3
+ LIVE_VALIDATIONS_OPTIONS = {
4
+ :failureMessage => :message,
5
+ :pattern => :with,
6
+ :onlyInteger => :only_integer
7
+ }
8
+ # more complicated mappings in map_configuration method
9
+
10
+ VALIDATION_METHODS = {
11
+ :presence => "Validate.Presence",
12
+ :numericality => "Validate.Numericality",
13
+ :format => "Validate.Format",
14
+ :length => "Validate.Length",
15
+ :acceptance => "Validate.Acceptance",
16
+ :confirmation => "Validate.Confirmation"
17
+ }
18
+
19
+
20
+ module ClassMethods
21
+
22
+ VALIDATION_METHODS.keys.each do |type|
23
+ define_method "validates_#{type}_of_with_live_validations".to_sym do |*attr_names|
24
+ send "validates_#{type}_of_without_live_validations".to_sym, *attr_names
25
+ define_validations(type, attr_names)
26
+ end
27
+ alias_method_chain "validates_#{type}_of".to_sym, :live_validations
28
+ end
29
+
30
+ def live_validations
31
+ @live_validations ||= {}
32
+ end
33
+
34
+ private
35
+
36
+ def define_validations(validation_type, attr_names)
37
+ conf = (attr_names.last.is_a?(Hash) ? attr_names.pop : {})
38
+ attr_names.each do |attr_name|
39
+ configuration = map_configuration(conf.dup, validation_type, attr_name)
40
+ add_live_validation(attr_name, validation_type, configuration)
41
+ end
42
+ end
43
+
44
+ def add_live_validation(attr_name, type, configuration = {})
45
+ @live_validations ||= {}
46
+ @live_validations[attr_name] ||= {}
47
+ @live_validations[attr_name][type] = configuration
48
+ end
49
+
50
+ def map_configuration(configuration, type = nil, attr_name = '')
51
+ LIVE_VALIDATIONS_OPTIONS.each do |live, rails|
52
+ configuration[live] = configuration.delete(rails)
53
+ end
54
+ if type == :numericality
55
+ if configuration[:onlyInteger]
56
+ configuration[:notAnIntegerMessage] = configuration.delete(:failureMessage)
57
+ else
58
+ configuration[:notANumberMessage] = configuration.delete(:failureMessage)
59
+ end
60
+ end
61
+ if type == :length and range = ( configuration.delete(:in) || configuration.delete(:within) )
62
+ configuration[:minimum] = range.begin
63
+ configuration[:maximum] = range.end
64
+ end
65
+ if type == :confirmation
66
+ configuration[:match] = self.to_s.underscore + '_' + attr_name.to_s + '_confirmation'
67
+ end
68
+ configuration[:validMessage] ||= ''
69
+ configuration.reject {|k, v| v.nil? }
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,17 @@
1
+ namespace :livevalidation do
2
+
3
+ PLUGIN_ROOT = File.dirname(__FILE__) + '/../'
4
+
5
+ desc 'Installs required javascript and stylesheet files to the public/ directory.'
6
+ task :install do
7
+ FileUtils.cp Dir[PLUGIN_ROOT + '/assets/javascripts/*.js'], RAILS_ROOT + '/public/javascripts'
8
+ FileUtils.cp Dir[PLUGIN_ROOT + '/assets/stylesheets/*.css'], RAILS_ROOT + '/public/stylesheets'
9
+ end
10
+
11
+ desc 'Removes the javascript and stylesheet for the plugin.'
12
+ task :remove do
13
+ FileUtils.rm %{live_validation.js}.collect { |f| RAILS_ROOT + "/public/javascripts/" + f }
14
+ FileUtils.rm %{live_validation.css}.collect { |f| RAILS_ROOT + "/public/stylesheets/" + f }
15
+ end
16
+
17
+ end
@@ -0,0 +1,214 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ require 'active_record'
4
+ require 'action_controller'
5
+ require 'action_controller/test_process'
6
+ require 'action_view'
7
+ require File.dirname(__FILE__) + '/../lib/live_validations'
8
+ require File.dirname(__FILE__) + '/../lib/form_helpers'
9
+ require File.dirname(__FILE__) + '/../test/resource'
10
+
11
+ class ResourcesController < ActionController::Base
12
+ def without_instance_var
13
+ render_form(:text, :name)
14
+ end
15
+
16
+ def without_live
17
+ @resource = Resource.new
18
+ render :inline => "<% form_for(:resource, :url => resources_path) do |f| %><%= f.text_field :name, :live => false %><% end %>"
19
+ end
20
+
21
+ def with_live
22
+ @resource = Resource.new
23
+ render :inline => "<% form_for(:resource, :url => resources_path) do |f| %><%= f.text_field :name, :live => true %><% end %>"
24
+ end
25
+
26
+ def with_string
27
+ @resource = Resource.new
28
+ render :inline => "<% form_for(:resource, :url => resources_path) do |f| %><%= f.text_field 'name' %><% end %>"
29
+ end
30
+
31
+ def with_text_area
32
+ @resource = Resource.new
33
+ render :inline => "<% form_for(:resource, :url => resources_path) do |f| %><%= f.text_area :name %><% end %>"
34
+ end
35
+
36
+ def name
37
+ @resource = Resource.new
38
+ render_form(:text, :name)
39
+ end
40
+
41
+ def amount
42
+ @resource = Resource.new
43
+ render_form(:text, :amount)
44
+ end
45
+
46
+ def password
47
+ @resource = Resource.new
48
+ render :inline => "<% form_for(:resource, :url => resources_path) do |f| %><%= f.password_field :password %><%= f.password_field :password_confirmation %><% end %>"
49
+ end
50
+
51
+ def rescue_action(e)
52
+ raise e
53
+ end
54
+
55
+ private
56
+
57
+ def render_form(type, method)
58
+ render :inline => "<% form_for(:resource, :url => resources_path) do |f| %><%= f.#{type}_field :#{method} %><% end %>"
59
+ end
60
+ end
61
+
62
+ ActionController::Routing::Routes.draw do |map|
63
+ map.resources :resources
64
+ map.connect ':controller/:action/:id'
65
+ end
66
+
67
+ class FormHelpersTest < Test::Unit::TestCase
68
+
69
+ def setup
70
+ @controller = ResourcesController.new
71
+ @request = ActionController::TestRequest.new
72
+ @response = ActionController::TestResponse.new
73
+ Resource.class_eval do # reset live validations
74
+ @live_validations = {}
75
+ end
76
+ ActionView::live_validations = true # reset default behaviour
77
+ end
78
+
79
+ def test_without_instance_var
80
+ get :without_instance_var
81
+ check_form_item :type => 'text', :name => 'name'
82
+ end
83
+
84
+ def test_without_live
85
+ Resource.class_eval do
86
+ validates_presence_of :name
87
+ end
88
+ get :without_live
89
+ check_form_item :type => 'text', :name => 'name'
90
+ end
91
+
92
+ def test_without_live_with_false_default
93
+ ActionView::live_validations = false
94
+ Resource.class_eval do
95
+ validates_presence_of :name
96
+ end
97
+ get :name
98
+ check_form_item :type => 'text', :name => 'name'
99
+ end
100
+
101
+ def test_with_live_with_false_default
102
+ ActionView::live_validations = false
103
+ Resource.class_eval do
104
+ validates_presence_of :name
105
+ end
106
+ get :with_live
107
+ check_form_item :type => 'text', :name => 'name' do |script|
108
+ assert_matches script, "var resource_name = new LiveValidation('resource_name');resource_name.add(Validate.Presence, {\"validMessage\": \"\"})"
109
+ end
110
+ end
111
+
112
+ def test_with_string
113
+ Resource.class_eval do
114
+ validates_presence_of :name
115
+ end
116
+ get :with_string
117
+ check_form_item :type => 'text', :name => 'name' do |script|
118
+ assert_matches script, "var resource_name = new LiveValidation('resource_name');resource_name.add(Validate.Presence, {\"validMessage\": \"\"})"
119
+ end
120
+ end
121
+
122
+ def test_with_text_area
123
+ Resource.class_eval do
124
+ validates_presence_of :name
125
+ end
126
+ get :with_text_area
127
+ assert_response :ok
128
+ assert_select 'form[action="/resources"]' do
129
+ assert_select "textarea[id='resource_name']"
130
+ assert_select 'script', "var resource_name = new LiveValidation('resource_name');resource_name.add(Validate.Presence, {\"validMessage\": \"\"})"
131
+ end
132
+ end
133
+
134
+ def test_presence
135
+ Resource.class_eval do
136
+ validates_presence_of :name
137
+ end
138
+ get :name
139
+ check_form_item :type => 'text', :name => 'name' do |script|
140
+ assert_matches script, "var resource_name = new LiveValidation('resource_name');resource_name.add(Validate.Presence, {\"validMessage\": \"\"})"
141
+ end
142
+ end
143
+
144
+ def test_presence_with_message
145
+ Resource.class_eval do
146
+ validates_presence_of :name, :message => 'is required'
147
+ end
148
+ get :name
149
+ check_form_item :type => 'text', :name => 'name' do |script|
150
+ assert_matches script, /var resource_name = new LiveValidation\('resource_name'\);resource_name.add\(Validate.Presence, \{(.+)\}\)/
151
+ assert_matches script, "\"validMessage\": \"\""
152
+ assert_matches script, "\"failureMessage\": \"is required\""
153
+ end
154
+ end
155
+
156
+ def test_numericality
157
+ Resource.class_eval do
158
+ validates_numericality_of :amount
159
+ end
160
+ get :amount
161
+ check_form_item :type => 'text', :name => 'amount' do |script|
162
+ assert_matches script, "var resource_amount = new LiveValidation('resource_amount');resource_amount.add(Validate.Numericality, {\"validMessage\": \"\"})"
163
+ end
164
+ end
165
+
166
+ def test_numericality_only_integer
167
+ Resource.class_eval do
168
+ validates_numericality_of :amount, :only_integer => true
169
+ end
170
+ get :amount
171
+ check_form_item :type => 'text', :name => 'amount' do |script|
172
+ assert_matches script, /var resource_amount = new LiveValidation\('resource_amount'\);resource_amount.add\(Validate.Numericality, \{(.*)\}\)/
173
+ assert_matches script, "\"onlyInteger\": true"
174
+ assert_matches script, "\"validMessage\": \"\""
175
+ end
176
+ end
177
+
178
+ def test_confirmation
179
+ Resource.class_eval do
180
+ validates_confirmation_of :password
181
+ end
182
+ get :password
183
+ check_form_item :type => 'password', :name => 'password' do |script|
184
+ assert_matches script, /var resource_password = new LiveValidation\('resource_password'\);resource_password.add\(Validate.Confirmation, \{(.*)\}\)/
185
+ assert_matches script, "\"match\": \"resource_password_confirmation\""
186
+ assert_matches script, "\"validMessage\": \"\""
187
+ end
188
+ end
189
+
190
+ private
191
+
192
+ def check_form_item(options = {}, &blk)
193
+ assert_response :ok
194
+ assert_select 'form[action="/resources"]' do
195
+ assert_select "input[type='#{options[:type]}'][id='resource_#{options[:name]}']"
196
+ if block_given?
197
+ assert_select 'script' do |element|
198
+ yield(element.to_s)
199
+ end
200
+ else
201
+ assert_select 'script', 0
202
+ end
203
+ end
204
+ end
205
+
206
+ def assert_matches(string, regexp)
207
+ if regexp.is_a?(Regexp)
208
+ assert string =~ regexp, "#{string} doesn't match #{regexp}"
209
+ else
210
+ assert string[regexp], "#{string} doesn't match #{regexp}"
211
+ end
212
+ end
213
+
214
+ end