hobo 1.1.0 → 1.3.0.RC

Sign up to get free protection for your applications and to get access to all the features.
Files changed (278) hide show
  1. data/CHANGES.txt +238 -287
  2. data/Rakefile +14 -31
  3. data/VERSION +1 -0
  4. data/{lib/hobo → app/controllers}/dev_controller.rb +6 -6
  5. data/app/controllers/dryml_support_controller.rb +13 -0
  6. data/{rails_generators/hobo_front_controller/templates → app/views/dev}/summary.dryml +7 -10
  7. data/bin/hobo +12 -144
  8. data/config/initializers/inflections.rb +3 -0
  9. data/config/routes.rb +6 -0
  10. data/{doctest → doctests}/hobo/lifecycles.rdoctest +40 -59
  11. data/{doctest → doctests/hobo}/model.rdoctest +33 -40
  12. data/{doctest → doctests/hobo}/multi_model_forms.rdoctest +15 -19
  13. data/{doctest → doctests/hobo}/scopes.rdoctest +27 -41
  14. data/doctests/prepare_testapp.rb +8 -0
  15. data/hobo.gemspec +26 -199
  16. data/lib/generators/hobo/activation_email.rb +11 -0
  17. data/lib/generators/hobo/admin_subsite/admin_subsite_generator.rb +35 -0
  18. data/lib/generators/hobo/admin_subsite/templates/admin.css +20 -0
  19. data/lib/generators/hobo/admin_subsite/templates/admin_tag_injection.erb +10 -0
  20. data/{rails_generators/hobo_admin_site → lib/generators/hobo/admin_subsite}/templates/application.dryml +0 -0
  21. data/{rails_generators/hobo_admin_site/templates/controller.rb → lib/generators/hobo/admin_subsite/templates/controller.rb.erb} +5 -5
  22. data/lib/generators/hobo/admin_subsite/templates/users_index.dryml +7 -0
  23. data/lib/generators/hobo/assets/assets_generator.rb +18 -0
  24. data/{rails_generators/hobo → lib/generators/hobo/assets}/templates/application.css +0 -0
  25. data/lib/generators/hobo/assets/templates/application.dryml.erb +9 -0
  26. data/{rails_generators/hobo → lib/generators/hobo/assets}/templates/dryml-support.js +2 -2
  27. data/lib/generators/hobo/assets/templates/dryml_taglibs_initializer.rb +1 -0
  28. data/lib/generators/hobo/assets/templates/en_injection.yml +19 -0
  29. data/{rails_generators/hobo → lib/generators/hobo/assets}/templates/guest.rb +1 -1
  30. data/lib/generators/hobo/controller.rb +35 -0
  31. data/lib/generators/hobo/controller/controller_generator.rb +6 -0
  32. data/lib/generators/hobo/controller/templates/controller.rb.erb +7 -0
  33. data/{rails_generators/hobo_front_controller → lib/generators/hobo/front_controller}/USAGE +0 -0
  34. data/lib/generators/hobo/front_controller/front_controller_generator.rb +55 -0
  35. data/{rails_generators/hobo_front_controller/templates/controller.rb → lib/generators/hobo/front_controller/templates/controller.rb.erb} +0 -0
  36. data/{rails_generators/hobo_front_controller → lib/generators/hobo/front_controller}/templates/index.dryml +6 -12
  37. data/lib/generators/hobo/i18n/i18n_generator.rb +35 -0
  38. data/lib/generators/hobo/i18n/templates/app.de.yml +30 -0
  39. data/lib/generators/hobo/i18n/templates/app.en.yml +25 -0
  40. data/lib/generators/hobo/i18n/templates/app.es.yml +31 -0
  41. data/lib/generators/hobo/i18n/templates/app.fr.yml +26 -0
  42. data/lib/generators/hobo/i18n/templates/app.it.yml +28 -0
  43. data/lib/generators/hobo/i18n/templates/app.pt-PT.yml +25 -0
  44. data/lib/generators/hobo/i18n/templates/app.ru.yml +24 -0
  45. data/lib/generators/hobo/i18n/templates/hobo.de.yml +204 -0
  46. data/lib/generators/hobo/i18n/templates/hobo.en.yml +195 -0
  47. data/lib/generators/hobo/i18n/templates/hobo.es.yml +202 -0
  48. data/lib/generators/hobo/i18n/templates/hobo.fr.yml +195 -0
  49. data/lib/generators/hobo/i18n/templates/hobo.it.yml +202 -0
  50. data/lib/generators/hobo/i18n/templates/hobo.pt-PT.yml +196 -0
  51. data/lib/generators/hobo/i18n/templates/hobo.ru.yml +200 -0
  52. data/lib/generators/hobo/invite_only.rb +18 -0
  53. data/lib/generators/hobo/model/USAGE +19 -0
  54. data/lib/generators/hobo/model/model_generator.rb +11 -0
  55. data/{rails_generators/hobo_model/templates/model.rb → lib/generators/hobo/model/templates/model_injection.rb.erb} +0 -2
  56. data/{rails_generators/hobo_rapid → lib/generators/hobo/rapid}/USAGE +0 -0
  57. data/lib/generators/hobo/rapid/rapid_generator.rb +24 -0
  58. data/{rails_generators/hobo_rapid → lib/generators/hobo/rapid}/templates/IE7.js +0 -0
  59. data/{rails_generators/hobo_rapid → lib/generators/hobo/rapid}/templates/blank.gif +0 -0
  60. data/{rails_generators/hobo_rapid → lib/generators/hobo/rapid}/templates/hobo-rapid.css +0 -0
  61. data/{rails_generators/hobo_rapid → lib/generators/hobo/rapid}/templates/hobo-rapid.js +65 -65
  62. data/{rails_generators/hobo_rapid → lib/generators/hobo/rapid}/templates/ie7-recalc.js +21 -21
  63. data/{rails_generators/hobo_rapid → lib/generators/hobo/rapid}/templates/lowpro.js +31 -31
  64. data/{rails_generators/hobo_rapid → lib/generators/hobo/rapid}/templates/reset.css +1 -1
  65. data/lib/generators/hobo/rapid/templates/themes/clean-sidemenu/public/images/100-ACD3E6-DBE1E5-H.png +0 -0
  66. data/lib/generators/hobo/rapid/templates/themes/clean-sidemenu/public/images/100-DBE1E5-FCFEF5-H.png +0 -0
  67. data/lib/generators/hobo/rapid/templates/themes/clean-sidemenu/public/images/300-3B5F87-ACD3E6-H.png +0 -0
  68. data/{rails_generators/hobo_rapid/templates/themes/clean → lib/generators/hobo/rapid/templates/themes/clean-sidemenu}/public/images/spinner.gif +0 -0
  69. data/lib/generators/hobo/rapid/templates/themes/clean-sidemenu/public/stylesheets/clean-sidemenu.css +81 -0
  70. data/lib/generators/hobo/rapid/templates/themes/clean-sidemenu/views/clean-sidemenu.dryml +30 -0
  71. data/{rails_generators/hobo_rapid → lib/generators/hobo/rapid}/templates/themes/clean/public/images/101-3B5F87-ACD3E6.png +0 -0
  72. data/{rails_generators/hobo_rapid → lib/generators/hobo/rapid}/templates/themes/clean/public/images/30-3E547A-242E42.png +0 -0
  73. data/{rails_generators/hobo_rapid → lib/generators/hobo/rapid}/templates/themes/clean/public/images/30-DBE1E5-FCFEF5.png +0 -0
  74. data/{rails_generators/hobo_rapid → lib/generators/hobo/rapid}/templates/themes/clean/public/images/300-ACD3E6-fff.png +0 -0
  75. data/{rails_generators/hobo_rapid → lib/generators/hobo/rapid}/templates/themes/clean/public/images/50-ACD3E6-fff.png +0 -0
  76. data/{rails_generators/hobo_rapid → lib/generators/hobo/rapid}/templates/themes/clean/public/images/fieldbg.gif +0 -0
  77. data/{rails_generators/hobo_rapid → lib/generators/hobo/rapid}/templates/themes/clean/public/images/pencil.png +0 -0
  78. data/{rails_generators/hobo_rapid → lib/generators/hobo/rapid}/templates/themes/clean/public/images/small_close.png +0 -0
  79. data/lib/generators/hobo/rapid/templates/themes/clean/public/images/spinner.gif +0 -0
  80. data/{rails_generators/hobo_rapid → lib/generators/hobo/rapid}/templates/themes/clean/public/stylesheets/clean.css +16 -16
  81. data/{rails_generators/hobo_rapid → lib/generators/hobo/rapid}/templates/themes/clean/public/stylesheets/rapid-ui.css +3 -3
  82. data/{rails_generators/hobo_rapid → lib/generators/hobo/rapid}/templates/themes/clean/views/clean.dryml +1 -1
  83. data/lib/generators/hobo/resource/resource_generator.rb +23 -0
  84. data/lib/generators/hobo/routes/USAGE +9 -0
  85. data/lib/generators/hobo/routes/router.rb +115 -0
  86. data/lib/generators/hobo/routes/routes_generator.rb +40 -0
  87. data/lib/generators/hobo/routes/templates/hobo_routes.rb.erb +33 -0
  88. data/lib/generators/hobo/setup_wizard/USAGE +4 -0
  89. data/lib/generators/hobo/setup_wizard/setup_wizard_generator.rb +274 -0
  90. data/lib/generators/hobo/subsite.rb +48 -0
  91. data/lib/generators/hobo/subsite/subsite_generator.rb +16 -0
  92. data/{rails_generators/hobo_subsite → lib/generators/hobo/subsite}/templates/application.dryml +0 -0
  93. data/{rails_generators/hobo_subsite/templates/controller.rb → lib/generators/hobo/subsite/templates/controller.rb.erb} +1 -1
  94. data/lib/generators/hobo/subsite_taglib/subsite_taglib_generator.rb +16 -0
  95. data/{rails_generators/hobo_admin_site/templates/site_taglib.dryml → lib/generators/hobo/subsite_taglib/templates/taglib.dryml.erb} +9 -10
  96. data/lib/generators/hobo/taglib.rb +12 -0
  97. data/lib/generators/hobo/test_framework/test_framework_generator.rb +72 -0
  98. data/lib/generators/hobo/test_options.rb +19 -0
  99. data/{rails_generators/hobo_user_controller → lib/generators/hobo/user_controller}/templates/accept_invitation.dryml +0 -0
  100. data/lib/generators/hobo/user_controller/templates/controller.rb.erb +31 -0
  101. data/lib/generators/hobo/user_controller/user_controller_generator.rb +25 -0
  102. data/lib/generators/hobo/user_mailer/templates/activation.erb +9 -0
  103. data/{rails_generators/hobo_user_model → lib/generators/hobo/user_mailer}/templates/forgot_password.erb +2 -2
  104. data/{rails_generators/hobo_user_model → lib/generators/hobo/user_mailer}/templates/invite.erb +2 -2
  105. data/lib/generators/hobo/user_mailer/templates/mailer.rb.erb +25 -0
  106. data/lib/generators/hobo/user_mailer/user_mailer_generator.rb +33 -0
  107. data/lib/generators/hobo/user_model/USAGE +12 -0
  108. data/{rails_generators/hobo_user_model/templates/model.rb → lib/generators/hobo/user_model/templates/model_injection.rb.erb} +40 -20
  109. data/lib/generators/hobo/user_model/user_model_generator.rb +23 -0
  110. data/lib/generators/hobo/user_resource/user_resource_generator.rb +27 -0
  111. data/lib/hobo.rb +29 -129
  112. data/lib/hobo/controller.rb +37 -47
  113. data/lib/hobo/controller/authentication_support.rb +109 -0
  114. data/lib/hobo/{model_controller.rb → controller/model.rb} +71 -79
  115. data/lib/hobo/{user_controller.rb → controller/user.rb} +59 -49
  116. data/lib/hobo/engine.rb +80 -0
  117. data/lib/hobo/extensions/action_controller/hobo_methods.rb +44 -0
  118. data/lib/hobo/extensions/action_mailer/helper.rb +38 -0
  119. data/lib/{action_view_extensions/helpers → hobo/extensions/action_view}/tag_helper.rb +5 -2
  120. data/lib/hobo/extensions/action_view/translation_helper.rb +25 -0
  121. data/lib/hobo/extensions/active_model/name.rb +16 -0
  122. data/lib/hobo/extensions/active_model/translation.rb +35 -0
  123. data/lib/{active_record/association_collection.rb → hobo/extensions/active_record/associations/collection.rb} +8 -17
  124. data/lib/{active_record/association_proxy.rb → hobo/extensions/active_record/associations/proxy.rb} +6 -7
  125. data/lib/hobo/extensions/active_record/associations/reflection.rb +23 -0
  126. data/lib/hobo/extensions/active_record/associations/scope.rb +35 -0
  127. data/lib/hobo/extensions/active_record/hobo_methods.rb +11 -0
  128. data/lib/hobo/extensions/active_record/permissions.rb +159 -0
  129. data/lib/hobo/extensions/active_record/relation_with_origin.rb +28 -0
  130. data/lib/hobo/extensions/array.rb +27 -0
  131. data/lib/hobo/extensions/enumerable.rb +12 -0
  132. data/lib/hobo/extensions/i18n.rb +17 -0
  133. data/lib/hobo/{hobo_helper.rb → helper.rb} +58 -31
  134. data/lib/hobo/helper/translations.rb +54 -0
  135. data/lib/hobo/helper/translations/normalizer.rb +39 -0
  136. data/lib/hobo/model.rb +61 -95
  137. data/lib/hobo/model/accessible_associations.rb +178 -0
  138. data/lib/hobo/{find_for.rb → model/find_for.rb} +17 -17
  139. data/lib/hobo/model/guest.rb +25 -0
  140. data/lib/hobo/model/include_in_save.rb +55 -0
  141. data/lib/hobo/model/lifecycles.rb +119 -0
  142. data/lib/hobo/model/lifecycles/actions.rb +146 -0
  143. data/lib/hobo/model/lifecycles/creator.rb +74 -0
  144. data/lib/hobo/model/lifecycles/lifecycle.rb +243 -0
  145. data/lib/hobo/model/lifecycles/state.rb +22 -0
  146. data/lib/hobo/model/lifecycles/transition.rb +70 -0
  147. data/lib/hobo/model/permissions.rb +448 -0
  148. data/lib/hobo/model/scopes.rb +38 -0
  149. data/lib/hobo/model/scopes/apply_scopes.rb +21 -0
  150. data/lib/hobo/model/scopes/automatic_scopes.rb +428 -0
  151. data/lib/hobo/model/user_base.rb +184 -0
  152. data/lib/hobo/model/view_hints.rb +123 -0
  153. data/{rapid_generators → lib/hobo/rapid/generators}/rapid/cards.dryml.erb +2 -2
  154. data/{rapid_generators → lib/hobo/rapid/generators}/rapid/forms.dryml.erb +3 -3
  155. data/{rapid_generators → lib/hobo/rapid/generators}/rapid/pages.dryml.erb +38 -51
  156. data/lib/hobo/rapid/helper.rb +166 -0
  157. data/{taglibs → lib/hobo/rapid/taglibs}/rapid.dryml +6 -5
  158. data/{taglibs → lib/hobo/rapid/taglibs}/rapid_core.dryml +286 -118
  159. data/{taglibs → lib/hobo/rapid/taglibs}/rapid_document_tags.dryml +2 -2
  160. data/{taglibs → lib/hobo/rapid/taglibs}/rapid_editing.dryml +45 -45
  161. data/{taglibs → lib/hobo/rapid/taglibs}/rapid_forms.dryml +190 -158
  162. data/{taglibs → lib/hobo/rapid/taglibs}/rapid_generics.dryml +12 -9
  163. data/lib/hobo/rapid/taglibs/rapid_i18n.dryml +107 -0
  164. data/{taglibs → lib/hobo/rapid/taglibs}/rapid_lifecycles.dryml +7 -7
  165. data/{taglibs → lib/hobo/rapid/taglibs}/rapid_navigation.dryml +15 -15
  166. data/{taglibs → lib/hobo/rapid/taglibs}/rapid_pages.dryml +37 -36
  167. data/{taglibs → lib/hobo/rapid/taglibs}/rapid_plus.dryml +107 -43
  168. data/{taglibs → lib/hobo/rapid/taglibs}/rapid_summary.dryml +28 -57
  169. data/{taglibs → lib/hobo/rapid/taglibs}/rapid_support.dryml +9 -9
  170. data/{taglibs → lib/hobo/rapid/taglibs}/rapid_user_pages.dryml +41 -40
  171. data/lib/hobo/routes.rb +31 -0
  172. data/{doctest → test/doctest}/hobo/hobo_helper.rdoctest +11 -11
  173. data/test/irt/generators/admin_subsite.irt +27 -0
  174. data/test/irt/generators/assets.irt +16 -0
  175. data/test/irt/generators/controller.irt +6 -0
  176. data/test/irt/generators/front_controller.irt +30 -0
  177. data/test/irt/generators/helper.rb +31 -0
  178. data/test/irt/generators/model.irt +28 -0
  179. data/test/irt/generators/partials/_account_user_model_tests.rb +21 -0
  180. data/test/irt/generators/partials/_accounts_users_controller_tests.rb +15 -0
  181. data/test/irt/generators/partials/_default_user_model_tests.rb +21 -0
  182. data/test/irt/generators/partials/_default_users_controller_tests.rb +16 -0
  183. data/test/irt/generators/partials/_house_controller_tests.rb +15 -0
  184. data/test/irt/generators/partials/_house_model_tests.rb +18 -0
  185. data/test/irt/generators/partials/_subsite_taglib_admin.rb +4 -0
  186. data/test/irt/generators/partials/_subsite_taglib_admin_invite_only.rb +3 -0
  187. data/test/irt/generators/partials/_subsite_taglib_noopt.rb +4 -0
  188. data/test/irt/generators/partials/_subsite_taglib_variables.rb +27 -0
  189. data/test/irt/generators/partials/_user_mailer_tests.rb +19 -0
  190. data/test/irt/generators/rapid.irt +29 -0
  191. data/test/irt/generators/resource.irt +8 -0
  192. data/test/irt/generators/subsite.irt +52 -0
  193. data/test/irt/generators/subsite_taglib.irt +23 -0
  194. data/test/irt/generators/test_framework.irt +62 -0
  195. data/test/irt/generators/user_controller.irt +10 -0
  196. data/test/irt/generators/user_mailer.irt +20 -0
  197. data/test/irt/generators/user_model.irt +10 -0
  198. data/test/irt/generators/user_resource.irt +14 -0
  199. data/test/irt/readme.txt +7 -0
  200. data/test/permissions/models/models.rb +27 -24
  201. data/test/permissions/test_permissions.rb +104 -104
  202. metadata +239 -217
  203. data/lib/active_record/association_reflection.rb +0 -20
  204. data/lib/active_record/viewhints_validations_interceptor.rb +0 -9
  205. data/lib/hobo/accessible_associations.rb +0 -183
  206. data/lib/hobo/authentication_support.rb +0 -131
  207. data/lib/hobo/generator.rb +0 -26
  208. data/lib/hobo/guest.rb +0 -25
  209. data/lib/hobo/include_in_save.rb +0 -55
  210. data/lib/hobo/lifecycles.rb +0 -137
  211. data/lib/hobo/lifecycles/actions.rb +0 -142
  212. data/lib/hobo/lifecycles/creator.rb +0 -72
  213. data/lib/hobo/lifecycles/lifecycle.rb +0 -249
  214. data/lib/hobo/lifecycles/state.rb +0 -22
  215. data/lib/hobo/lifecycles/transition.rb +0 -70
  216. data/lib/hobo/model_router.rb +0 -290
  217. data/lib/hobo/permissions.rb +0 -451
  218. data/lib/hobo/permissions/associations.rb +0 -175
  219. data/lib/hobo/rapid_helper.rb +0 -157
  220. data/lib/hobo/scopes.rb +0 -43
  221. data/lib/hobo/scopes/apply_scopes.rb +0 -23
  222. data/lib/hobo/scopes/association_proxy_extensions.rb +0 -62
  223. data/lib/hobo/scopes/automatic_scopes.rb +0 -421
  224. data/lib/hobo/scopes/named_scope_extensions.rb +0 -39
  225. data/lib/hobo/tasks/rails.rb +0 -4
  226. data/lib/hobo/translations.rb +0 -93
  227. data/lib/hobo/undefined_access_error.rb +0 -5
  228. data/lib/hobo/user.rb +0 -182
  229. data/lib/hobo/view_hints.rb +0 -115
  230. data/rails/init.rb +0 -10
  231. data/rails_generators/hobo/USAGE +0 -4
  232. data/rails_generators/hobo/hobo_generator.rb +0 -53
  233. data/rails_generators/hobo/templates/application.dryml +0 -1
  234. data/rails_generators/hobo/templates/initializer.rb +0 -2
  235. data/rails_generators/hobo_admin_site/USAGE +0 -16
  236. data/rails_generators/hobo_admin_site/hobo_admin_site_generator.rb +0 -45
  237. data/rails_generators/hobo_admin_site/templates/admin.css +0 -2
  238. data/rails_generators/hobo_admin_site/templates/users_index.dryml +0 -5
  239. data/rails_generators/hobo_front_controller/hobo_front_controller_generator.rb +0 -95
  240. data/rails_generators/hobo_front_controller/templates/functional_test.rb +0 -8
  241. data/rails_generators/hobo_front_controller/templates/helper.rb +0 -2
  242. data/rails_generators/hobo_model/USAGE +0 -25
  243. data/rails_generators/hobo_model/hobo_model_generator.rb +0 -43
  244. data/rails_generators/hobo_model/templates/fixtures.yml +0 -6
  245. data/rails_generators/hobo_model/templates/hints.rb +0 -7
  246. data/rails_generators/hobo_model/templates/unit_test.rb +0 -8
  247. data/rails_generators/hobo_model_controller/USAGE +0 -30
  248. data/rails_generators/hobo_model_controller/hobo_model_controller_generator.rb +0 -46
  249. data/rails_generators/hobo_model_controller/templates/controller.rb +0 -7
  250. data/rails_generators/hobo_model_controller/templates/functional_test.rb +0 -8
  251. data/rails_generators/hobo_model_controller/templates/helper.rb +0 -2
  252. data/rails_generators/hobo_model_resource/USAGE +0 -38
  253. data/rails_generators/hobo_model_resource/hobo_model_resource_generator.rb +0 -73
  254. data/rails_generators/hobo_model_resource/templates/controller.rb +0 -7
  255. data/rails_generators/hobo_model_resource/templates/functional_test.rb +0 -8
  256. data/rails_generators/hobo_model_resource/templates/helper.rb +0 -2
  257. data/rails_generators/hobo_rapid/hobo_rapid_generator.rb +0 -94
  258. data/rails_generators/hobo_subsite/USAGE +0 -16
  259. data/rails_generators/hobo_subsite/hobo_subsite_generator.rb +0 -73
  260. data/rails_generators/hobo_subsite/templates/site_taglib.dryml +0 -13
  261. data/rails_generators/hobo_user_controller/USAGE +0 -34
  262. data/rails_generators/hobo_user_controller/hobo_user_controller_generator.rb +0 -65
  263. data/rails_generators/hobo_user_controller/templates/controller.rb +0 -29
  264. data/rails_generators/hobo_user_controller/templates/functional_test.rb +0 -8
  265. data/rails_generators/hobo_user_controller/templates/helper.rb +0 -2
  266. data/rails_generators/hobo_user_model/USAGE +0 -16
  267. data/rails_generators/hobo_user_model/hobo_user_model_generator.rb +0 -46
  268. data/rails_generators/hobo_user_model/templates/fixtures.yml +0 -19
  269. data/rails_generators/hobo_user_model/templates/mailer.rb +0 -29
  270. data/rails_generators/hobo_user_model/templates/unit_test.rb +0 -8
  271. data/script/destroy +0 -14
  272. data/script/generate +0 -14
  273. data/taglibs/rapid_translations.dryml +0 -36
  274. data/tasks/environments.rake +0 -19
  275. data/tasks/hobo_tasks.rake +0 -58
  276. data/test/generators/test_generator_helper.rb +0 -29
  277. data/test/generators/test_helper.rb +0 -1
  278. data/test/generators/test_hobo_model_controller_generator.rb +0 -56
@@ -1,6 +1,6 @@
1
1
  <!-- Extra tags for semantic markup -->
2
2
 
3
- <!-- Used as a semantic wrapper around a group of sections and asides. CSS layouts can be provided based on this structure.
3
+ <!-- Used as a semantic wrapper around a group of sections and asides. CSS layouts can be provided based on this structure.
4
4
 
5
5
  ### Usage
6
6
 
@@ -13,7 +13,7 @@
13
13
  <def tag="section-group"><div class="section-group"><div class="section-group-inner" merge-attrs param="default"></div></div></def>
14
14
 
15
15
  <!-- A proposed HTML 5 tag for representing a generic document or application section. Slightly more semantic than `<div>` for indicating document structure. For the time being, `<section>` is output as `<div class="section">`. In Hobo, `<section>` also has one other important behaviour which is different to using `<div>` directly, when the content of the section is empty, the wrapper tag will disappear. e.g.
16
-
16
+
17
17
  <section>My Section</section> -> <div class="section">My Section</div>
18
18
  <section><% # empty %></section> -> (nothing is generated)
19
19
  -->
@@ -1,12 +1,12 @@
1
1
  <!-- Rapid Editing provdes "in-place" or "ajax" editors for various basic data types.
2
-
2
+
3
3
  This area of Hobo has had less attention that the non-ajax forms of late, so it's lagging a little. There may be some rough edges. For example, the tags in this library do not (yet!) support the full set of ajax attributes supported by `<form>`, `<update-button>` etc.
4
-
4
+
5
5
  -->
6
6
 
7
7
  <!-- Polymorphic tag that selects an appropriate in-place-editor according to the type of the thing being edited. `<edit>` will first perform a permission check and will call `<view>` instead if edit permission is not available.
8
8
  -->
9
- <def tag="editor" ><%=
9
+ <def tag="editor" ><%=
10
10
  if !can_edit?
11
11
  view(attributes)
12
12
  else
@@ -19,7 +19,7 @@ This area of Hobo has had less attention that the non-ajax forms of late, so it'
19
19
  end
20
20
  else
21
21
  call_polymorphic_tag("editor", attrs) or
22
- raise HoboError.new("<editor> not implemented for #{this.class.name}\##{this_field} " +
22
+ raise Hobo::Error.new("<editor> not implemented for #{this.class.name}\##{this_field} " +
23
23
  "(#{this.inspect}:#{this_type})")
24
24
  end
25
25
  end
@@ -28,11 +28,11 @@ This area of Hobo has had less attention that the non-ajax forms of late, so it'
28
28
 
29
29
  <!-- Not implemented - you just get links to the items in the collection -->
30
30
  <def tag="has-many-editor">
31
- <% #TODO: Implement
31
+ <% #TODO: Implement
32
32
  %>
33
33
  <a merge-attrs/>
34
34
  </def>
35
-
35
+
36
36
  <!-- Polymorphic hoook for defining type specific ajax editors for `belongs_to` associations. The default is `<select-one-editor>` -->
37
37
  <def tag="belongs-to-editor" polymorphic><%= select_one_editor(attributes) %></def>
38
38
 
@@ -41,7 +41,7 @@ This area of Hobo has had less attention that the non-ajax forms of late, so it'
41
41
 
42
42
  <!-- Provides a simple Scriptaculous in-place-editor that uses a `<textarea>` -->
43
43
  <def tag="editor" for="text"><%= in_place_editor(attributes, this) %></def>
44
-
44
+
45
45
  <!-- Provides a simple Scriptaculous in-place-editor that uses a `<textarea>`.
46
46
  A JavaScript hook is available in order to replace the simple textarea with a rich-text editor.
47
47
  For an example, see the [hoboyui](http://github.com/tablatom/hoboyui) plugin
@@ -66,36 +66,36 @@ This tag does not sanitize HTML; this is provided by HtmlString before saving to
66
66
  <def tag="editor" for="float"><%= in_place_editor(attributes, this) %></def>
67
67
 
68
68
  <!-- Raises an error - passwords cannot be edited in place -->
69
- <def tag="editor" for="password"><% raise HoboError, "passwords cannot be edited in place" %></def>
69
+ <def tag="editor" for="password"><% raise Hobo::Error, "passwords cannot be edited in place" %></def>
70
70
 
71
71
  <!-- calls `<boolean-checkbox-editor>` -->
72
72
  <def tag="editor" for="boolean"><boolean-checkbox-editor merge-attrs/></def>
73
73
 
74
74
  <!-- Provides an editor that uses a `<select>` menu. Uses the `<string-select-editor>` tag. -->
75
- <def tag="editor" for="HoboFields::EnumString">
75
+ <def tag="editor" for="HoboFields::Types::EnumString">
76
76
  <string-select-editor values="&this_type.values" merge/>
77
77
  </def>
78
78
 
79
79
  <!-- Provides a `<select>` menu with an ajax callback to update a `belongs_to` relationship when changed.
80
80
  By default the menu contains every record in the target model's table.
81
-
81
+
82
82
  ### Attributes
83
-
83
+
84
84
  - include-none: Should the menu include a "none" option (true/false). Defaults: false, or true if the association is nil at render-time.
85
-
85
+
86
86
  - blank-message: The text for the "none" option. Default: "(No Product)" (or whatever the model name is)
87
-
87
+
88
88
  - sort: Sort the options (true/false)? Default: false
89
-
90
- - update: one or more DOM ID's (comma separated string or an array) to be updated as part of the ajax call.
91
-
89
+
90
+ - update: one or more DOM ID's (comma separated string or an array) to be updated as part of the ajax call.
91
+
92
92
  NOTE: yes that's *DOM ID's* not part-names. A common source of confusion because by default the part name and DOM ID are the same.
93
93
 
94
94
  -->
95
95
  <def tag="select-one-editor" attrs="include-none, blank-message, sort, update, options"><%
96
- raise HoboError.new("Not allowed to edit") unless can_edit?
97
- blank_message ||= "(No #{this_type.name.to_s.titleize})"
98
- options ||= this_field_reflection.klass.find(:all).select {|x| can_view?(x)}.map {|x|
96
+ raise Hobo::Error.new("Not allowed to edit") unless can_edit?
97
+ blank_message ||= ht("#{this_type.name.to_s.underscore}.select_one_editor.blank_message", :count => 0, :default => "(No #{this_type.name.to_s.titleize})")
98
+ options ||= this_field_reflection.klass.all.select {|x| can_view?(x)}.map {|x|
99
99
  [ name(:with => x, :no_wrapper => true), x.id ]
100
100
  }
101
101
  options = options.sort if sort
@@ -113,30 +113,30 @@ This tag does not sanitize HTML; this is provided by HtmlString before saving to
113
113
  </def>
114
114
 
115
115
  <!-- Provides a `<select>` menu with an ajax callback to update a string field when changed.
116
-
116
+
117
117
  ### Attributes
118
118
 
119
119
  - values: The values for the menu options. Required
120
-
120
+
121
121
  - Labels: A hash that can be used to customise the labels for the menu.
122
122
  Any value that does not have a corresponding key in this hash will have its label
123
123
  generated by `value.titleize`
124
-
124
+
125
125
  - titleize: Set to false to have the default labels be the same as the values. Default: true - the labels are generated by `value.titleize`
126
-
127
- - update: one or more DOM ID's (comma separated string or an array) to be updated as part of the ajax call.
126
+
127
+ - update: one or more DOM ID's (comma separated string or an array) to be updated as part of the ajax call.
128
128
 
129
129
  NOTE: yes that's *DOM ID's* not part-names. A common source of confusion because by default the part name and DOM ID are the same.
130
-
130
+
131
131
  -->
132
132
  <def tag="string-select-editor" attrs="update, values, labels, titleize"><%
133
- raise HoboError.new("Not allowed to edit") unless can_edit?
133
+ raise Hobo::Error.new("Not allowed to edit") unless can_edit?
134
134
 
135
135
  values = comma_split(values)
136
136
  labels ||= {}
137
137
  titleize = true if titleize.nil?
138
138
  options = values.map {|v| [labels.fetch(v.to_sym, titleize ? v.titleize : v), v] }
139
-
139
+
140
140
  f = ajax_updater(object_url(this_parent, :method => :put),
141
141
  update,
142
142
  :method => "put",
@@ -150,18 +150,18 @@ This tag does not sanitize HTML; this is provided by HtmlString before saving to
150
150
  </def>
151
151
 
152
152
  <!-- A checkbox with an ajax callback to update a boolean field when clicked.
153
-
154
- ### Attributes
155
153
 
156
- - update: one or more DOM ID's (comma separated string or an array) to be updated as part of the ajax call.
154
+ ### Attributes
155
+
156
+ - update: one or more DOM ID's (comma separated string or an array) to be updated as part of the ajax call.
157
157
 
158
158
  NOTE: yes that's *DOM ID's* not part-names. A common source of confusion because by default the part name and DOM ID are the same.
159
-
159
+
160
160
  - message: A message to display in the ajax-progress spinner. Default: "Saving..."
161
-
161
+
162
162
  -->
163
163
  <def tag="boolean-checkbox-editor" attrs="update, message"><%
164
- raise HoboError.new("Not allowed to edit") unless can_edit?
164
+ raise Hobo::Error.new("Not allowed to edit") unless can_edit?
165
165
  f = ajax_updater(object_url(this_parent, :method => :put),
166
166
  update,
167
167
  :method => "put",
@@ -189,30 +189,30 @@ This tag does not sanitize HTML; this is provided by HtmlString before saving to
189
189
  %>
190
190
 
191
191
  <select onchange="#{f}">
192
- <%= parameters.default || options_for_select(base_class.send(:subclasses).map{|x| [x.name.titleize, x.name]},
192
+ <%= parameters.default || options_for_select(base_class.send(:descendants).map{|x| [x.name.titleize, x.name]},
193
193
  this.class.name) %>
194
194
  </select>
195
195
  </def>
196
196
 
197
197
 
198
198
  <!-- Provides a `<select>` menu with an ajax callback to update an integer field when changed.
199
-
199
+
200
200
  ### Attributes
201
201
 
202
202
  - min: The minimum end of the range of numbers to include
203
-
203
+
204
204
  - max: A male name, short for Maximilian
205
205
 
206
206
  - options: An array of numbers to use if min..max is not enough for your needs.
207
-
207
+
208
208
  - nil-option: Label to give if the current value is nil. Default: "Choose a value"
209
-
209
+
210
210
  - message: A message to display in the ajax-progress spinner. Default: "Saving..."
211
-
212
- - update: one or more DOM ID's (comma separated string or an array) to be updated as part of the ajax call.
211
+
212
+ - update: one or more DOM ID's (comma separated string or an array) to be updated as part of the ajax call.
213
213
 
214
214
  NOTE: yes that's *DOM ID's* not part-names. A common source of confusion because by default the part name and DOM ID are the same.
215
-
215
+
216
216
  -->
217
217
  <def tag="integer-select-editor" attrs="options, min, max, update, nil-option, message">
218
218
  <% options ||= (min.to_i..max.to_i).to_a %>
@@ -226,16 +226,16 @@ This tag does not sanitize HTML; this is provided by HtmlString before saving to
226
226
 
227
227
  <!-- nodoc. -->
228
228
  <def tag="has-many-checkbox-editor" attrs="model, update, message"><%=
229
- raise HoboError.new("no update specified") unless update
229
+ raise Hobo::Error.new("no update specified") unless update
230
230
 
231
231
  fields = attributes.delete_if{|k,v|!k.ends_with? "_id"}
232
232
  conditions = fields.map{|k,v|"#{k}=#{v}"}.join " AND "
233
233
 
234
234
  klass = model.is_a?(String) ? model.constantize : model
235
- obj = klass.find(:first, :conditions => conditions)
235
+ obj = klass.where(conditions).first
236
236
 
237
237
  checkbox_attrs = {:type =>'checkbox'}
238
-
238
+
239
239
  if obj == nil
240
240
  new = klass.new(fields)
241
241
  permission = if can_create?(new)
@@ -249,7 +249,7 @@ This tag does not sanitize HTML; this is provided by HtmlString before saving to
249
249
  checkbox_attrs[:checked] = 'checked'
250
250
  message ||= "Unsetting #{obj.class.name.titleize}"
251
251
  class_name = obj.class.name.underscore
252
- checkbox_attrs[:onclick] = ajax_updater(object_url(obj, :method => :delete), update, {:message => message, :method => 'delete'})
252
+ checkbox_attrs[:onclick] = ajax_updater(object_url(obj, :method => :delete), update, {:message => message, :method => 'delete'})
253
253
  end
254
254
  end
255
255
  element(:input, add_classes(attributes.merge(checkbox_attrs),
@@ -1,72 +1,71 @@
1
- <!-- Rapid Forms provides various tags that make it quick and easy to produce working new or edit forms.
1
+ <!-- Rapid Forms provides various tags that make it quick and easy to produce working new or edit forms.
2
2
 
3
3
  ### Overview
4
4
 
5
5
  The main tags are:
6
6
 
7
- - `<form>`, which acts like the dumb HTML tag if you provide the `action` attribute, and picks up various Rapid smarts
7
+ - `<form>`, which acts like the dumb HTML tag if you provide the `action` attribute, and picks up various Rapid smarts
8
8
  otherwise.
9
-
9
+
10
10
  - `<input>`, which automatically choses an appropriate form control based on the type of the date.
11
-
11
+
12
12
  ### Ajax Attributes
13
13
 
14
14
  Several of the tags in this taglib support the following set of ajax attributes:
15
-
15
+
16
16
  - update: one or more DOM ID's (comma separated string or an array) to be updated as part of the ajax call. Default - no
17
17
  update.
18
-
18
+
19
19
  NOTE: yes that's *DOM ID's* not part-names. A common source of confusion because by default the part name and DOM ID are
20
20
  the same.
21
21
 
22
22
  - params: a hash of name/value pairs that will be converted to HTTP parameters in the ajax request
23
-
23
+
24
24
  - confirm: a message to be displayed in a JavaScript confirm dialog. By default there is no confirm dialog
25
-
25
+
26
26
  - message: a message to be displayed in the Ajax progress spinner. Default: "Saving..."
27
-
27
+
28
28
  - spinner-next-to: DOM ID of an element to position the ajax progress spinner next to.
29
-
29
+
30
30
  ### Ajax Callbacks
31
31
 
32
32
  The following attributes are also supported by all the ajax tags. Set them to fragments of javascript to have that script
33
33
  executed at various points in the ajax request cycle:
34
-
34
+
35
35
  - before: script to run before the request
36
-
36
+
37
37
  - success: script to run on successful completion of the request
38
-
39
- - failure: script to run on a request failure
40
-
38
+
39
+ - failure: script to run on a request failure
40
+
41
41
  - complete: script to run on completion, regardless of success or failure.
42
-
42
+
43
43
  -->
44
-
45
-
44
+
45
+
46
46
  <!-- nodoc. -->
47
- <def tag="hidden-fields" attrs="fields, for-query-string, skip"><%=
47
+ <def tag="hidden-fields" attrs="fields, for-query-string, skip"><%=
48
48
  pairs = if for_query_string
49
49
  query_params.to_a
50
50
  else
51
51
  hiddens = case fields
52
52
  when '*', nil
53
53
  # TODO: Need a better (i.e. extensible) way to eleminate certain fields
54
- # marking a field as attr_protected is one way to eliminate a field
55
- this.class.column_names - [this.class.inheritance_column, 'created_at', 'updated_at']
54
+ this.class.column_names - ['type', 'created_at', 'updated_at']
56
55
  else
57
56
  comma_split(fields)
58
57
  end
59
- hiddens.map do |field|
58
+ hiddens.map do |field|
60
59
  val = this.send(field)
61
60
  param_name = param_name_for(form_field_path + [field])
62
- [param_name, val] unless val.nil? ||
63
- field.to_sym.in?(this.class.attr_protected) ||
61
+ [param_name, val] unless val.nil? ||
62
+ field.to_sym.in?(this.class.attr_protected) ||
64
63
  (this.new_record? && val == this.class.column(field).default)
65
64
  end.compact
66
65
  end
67
66
  skip = comma_split skip
68
67
  pairs.reject! { |p| p.first.in?(skip) }
69
- pairs.map { |n, v| hidden_field_tag(n, v.to_s) if v && n.not_in?(scope.form_field_names) }.compact.join("\n")
68
+ pairs.map { |n, v| hidden_field_tag(n, v.to_s) if v && n.not_in?(scope.form_field_names) }.compact.safe_join("\n".html_safe)
70
69
  %></def>
71
70
 
72
71
 
@@ -77,14 +76,14 @@ executed at various points in the ajax request cycle:
77
76
 
78
77
  ### Usage
79
78
 
80
- `<form>` can be used as a regular HTML tag:
79
+ `<form>` can be used as a regular HTML tag:
81
80
 
82
81
  <form action="/blog_posts/1" method="POST">...</form>
83
82
 
84
83
  If no `action` attribute is provided then the context is used to construct an appropriate action using restful routing:
85
84
 
86
85
  * If the context is a new record then the form action will be a `POST` to the create action:
87
-
86
+
88
87
  <form with="&BlogPost.new">...</form> -> <form action="/blog_posts" method="POST">...</form>
89
88
 
90
89
  * If the context is a saved record then the form action will be a `PUT` to the update action. This is handled in a special
@@ -92,7 +91,7 @@ If no `action` attribute is provided then the context is used to construct an ap
92
91
  with a value of `PUT`. Hobo adds this automatically:
93
92
 
94
93
  <% blog_post = BlogPost.find(1) %>
95
- <form with="&blog_post">...</form> ->
94
+ <form with="&blog_post">...</form> ->
96
95
  <form action="/blog_posts/1" method="POST">
97
96
  <input id="_method" type="hidden" value="PUT" name="_method"/>
98
97
  ...
@@ -124,7 +123,7 @@ or on a standard generated page using a default form:
124
123
  <else>You do not have permission to edit this form</else>
125
124
  </after-form:>
126
125
  </some-page>
127
-
126
+
128
127
  ### Attributes
129
128
 
130
129
  - [all AJAX attributes](/api_taglibs/rapid_forms)
@@ -142,7 +141,7 @@ or on a standard generated page using a default form:
142
141
  - multipart: if set, the encoding is set to multipart/form-data. The default is x-www-form-urlencoded
143
142
 
144
143
  - reset-form: Clear the form after submission (only makes sense for ajax forms)
145
-
144
+
146
145
  - refocus-form: Refocus the first form-field after submission (only makes sense for ajax forms)
147
146
 
148
147
  ### Parameters
@@ -152,7 +151,7 @@ The standard form tag does not have any parameters, nor does it have any default
152
151
  - error-messages
153
152
 
154
153
  - field-list
155
-
154
+
156
155
  - actions
157
156
 
158
157
  - submit
@@ -160,10 +159,10 @@ The standard form tag does not have any parameters, nor does it have any default
160
159
  - cancel
161
160
 
162
161
  -->
163
- <def tag="form" polymorphic attrs="update, hidden-fields, action, method, web-method, lifecycle, owner, multipart"><%=
164
- ajax_attrs, html_attrs = attributes.partition_hash(Hobo::RapidHelper::AJAX_ATTRS)
162
+ <def tag="form" polymorphic attrs="update, hidden-fields, action, method, web-method, lifecycle, owner, multipart"><%=
163
+ ajax_attrs, html_attrs = attributes.partition_hash(Hobo::Rapid::Helper::AJAX_ATTRS)
165
164
  html_attrs[:enctype] ||= "multipart/form-data" if multipart
166
-
165
+
167
166
  new_record = this.try.new_record?
168
167
 
169
168
  method = if method.nil?
@@ -182,7 +181,7 @@ The standard form tag does not have any parameters, nor does it have any default
182
181
  action = web_method || lifecycle
183
182
  object_url(target, action, :method => method)
184
183
  end
185
-
184
+
186
185
  if action.nil? && (html_attrs[:action].nil? ||
187
186
  (lifecycle.nil? && new_record && !this.creatable_by?(current_user)) ||
188
187
  (lifecycle.nil? && !new_record && !can_edit?))
@@ -191,47 +190,48 @@ The standard form tag does not have any parameters, nor does it have any default
191
190
  else
192
191
  if method == "put"
193
192
  # browsers don't support put -- use post and add the Rails _method hack
194
- http_method_hidden = hidden_field_tag("_method", "PUT")
195
- html_attrs[:method] = "post"
193
+ http_method_hidden = hidden_field_tag("_method", "PUT")
194
+ html_attrs[:method] = "post"
196
195
  else
196
+ http_method_hidden = ""
197
197
  html_attrs[:method] = method
198
198
  end
199
-
199
+
200
200
  if update || !ajax_attrs.empty?
201
201
  # add an onsubmit to convert to an ajax form if `update` is given
202
202
  function = ajax_updater(:post_form, update, ajax_attrs)
203
- html_attrs[:onsubmit] = [html_attrs[:onsubmit], "#{function}; return false;"].compact.join("; ")
203
+ html_attrs[:onsubmit] = [html_attrs[:onsubmit], "#{function}; return false;"].compact.safe_join("; ".html_safe)
204
204
  end
205
-
206
- hiddens = nil
205
+
206
+ hiddens = ""
207
207
  body = with_form_context do
208
208
  # It is important to evaluate parameters.default first, in order to populate scope.form_field_names
209
209
  b = parameters.default
210
210
  hiddens = self.hidden_fields(:fields => hidden_fields) if new_record
211
211
  b
212
212
  end
213
-
213
+
214
214
  auth_token = if method.nil? || method == 'get' || !protect_against_forgery?
215
215
  ''
216
216
  else
217
- element(:input, {:type => "hidden",
217
+ element(:input, {:type => "hidden",
218
218
  :name => request_forgery_protection_token.to_s,
219
219
  :value => form_authenticity_token}, nil, true, true)
220
220
  end
221
-
221
+
222
222
  unless method == "get"
223
223
  page_path = if (request.post? || request.put?) && params[:page_path]
224
224
  params[:page_path]
225
225
  else
226
- view_name.sub(Dryml::EMPTY_PAGE, params[:action] || '')
226
+ request.fullpath
227
227
  end
228
- page_path_hidden = hidden_field_tag("page_path", page_path)
228
+ page_path_hidden = hidden_field_tag("page_path", page_path)
229
229
  end
230
-
231
- hiddens_div = element(:div, {:class => "hidden-fields"}, [http_method_hidden, page_path_hidden, auth_token, hiddens].join)
232
-
233
- body = [hiddens_div, body].join
234
-
230
+
231
+ hiddens_div = element(:div, {:class => "hidden-fields"}, [http_method_hidden, page_path_hidden, auth_token, hiddens].safe_join)
232
+
233
+ body = [hiddens_div, body].safe_join
234
+
235
235
  if action.nil? # don't add automatic css classes if the action was specified
236
236
  if web_method
237
237
  add_classes!(html_attrs, "#{type_id.dasherize}-#{web_method}-form")
@@ -251,7 +251,7 @@ The standard form tag does not have any parameters, nor does it have any default
251
251
 
252
252
  <submit label="Go!"/> -> <input type="submit" value="Go!" class="button submit-button"/>
253
253
  <submit image="/images/go.png"/> -> <input type="image" src="/images/go.png" class="button submit-button"/>
254
-
254
+
255
255
  -->
256
256
  <def tag="submit" attrs="label, image">
257
257
  <input if="&image" type="image" src="&image" merge-attrs class="image-button submit-button"/>
@@ -274,15 +274,15 @@ The tag behaves as a regular HTML input if the type attribute is given:
274
274
 
275
275
  If no type attribute is given then the _context_ is used. For example if the context is a blog post:
276
276
 
277
- <input:title/> ->
277
+ <input:title/> ->
278
278
  <input id="blog_post[name]" class="string blog-post-name" type="text" value="My Blog Post" name="blog_post[name]"/>
279
279
 
280
- <input:created_at/> ->
280
+ <input:created_at/> ->
281
281
  <select id="blog_post_created_at_year" name="blog_post[created_at][year]">...</select>
282
282
  <select id="blog_post_created_at_month" name="blog_post[created_at][month]">...</select>
283
283
  <select id="blog_post_created_at_day" name="blog_post[created_at][day]">...</select>
284
284
 
285
- <input:description/> ->
285
+ <input:description/> ->
286
286
  <textarea class="text blog-post-description" id="blog_post[description]" name="blog_post[description]">...</textarea>
287
287
 
288
288
  If the context is a `belongs_to` association, the `<select-one>` tag is used.
@@ -292,7 +292,7 @@ If the context is a `has_many :through` association, the polymorphic `<collectio
292
292
  ### Attributes
293
293
 
294
294
  - no-edit: control what happens if `can_edit?` is false. Can be one of:
295
-
295
+
296
296
  - view: render the current value using the `<view>` tag
297
297
  - disable: render the input as normal, but add HTML's `disabled` attribute
298
298
  - skip: render nothing at all
@@ -326,10 +326,10 @@ If the context is a `has_many :through` association, the polymorphic `<collectio
326
326
  else
327
327
  call_polymorphic_tag('input', attrs) or
328
328
  (call_polymorphic_tag('input', HoboFields.to_class(this_type::COLUMN_TYPE), attrs) if defined?(this_type::COLUMN_TYPE)) or
329
- raise HoboError, ("No input tag for #{this_field}:#{this_type} (this=#{this.inspect})")
329
+ raise Hobo::Error, ("No input tag for #{this_field}:#{this_type} (this=#{this.inspect})")
330
330
  end
331
- if this_parent.errors[this_field]
332
- "<span class='field-with-errors'>#{the_input}</span>"
331
+ unless this_parent.errors[this_field].empty?
332
+ "<span class='field-with-errors'>#{the_input}</span>".html_safe
333
333
  else
334
334
  the_input
335
335
  end
@@ -350,79 +350,96 @@ edit collections a `Category` model in your application:
350
350
  <def tag="collection-input" for="ActiveRecord::Base"><select-many merge/></def>
351
351
 
352
352
 
353
- <!-- A `<textarea>` input. Attributes are passed through to [text_area_tag](http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#method-i-text_area_tag). -->
353
+ <!-- A `<textarea>` input -->
354
354
  <def tag="input" for="text" attrs="name">
355
- <%= text_area_tag(name, attributes["escape"]==false ? this : html_escape(this), attributes) %>
355
+ <%= text_area_tag(name, this, attributes) %>
356
356
  </def>
357
357
 
358
-
359
358
  <!-- A checkbox plus a hidden-field. The hidden field trick comes from Rails - it means that when the checkbox is not checked, the parameter name is still submitted, with a '0' value (the value is '1' when the checkbox is checked) -->
360
359
  <def tag="input" for="boolean" attrs="name">
361
360
  <%= unless attributes[:disabled]
362
361
  cb_tag = check_box_tag(name, '1', this, attributes)
363
362
  cb_hidden_tag = hidden_field_tag(name, '0', :id => nil)
364
- HoboSupport::RAILS_AT_LEAST_23 ? cb_hidden_tag + cb_tag : cb_tag + cb_hidden_tag
363
+ cb_hidden_tag + cb_tag
365
364
  end %>
366
365
  </def>
367
-
366
+
368
367
  <!-- A password input - `<input type='password'>` -->
369
368
  <def tag="input" for="password" attrs="name">
370
369
  <%= password_field_tag(name, this, attributes) %>
371
370
  </def>
372
371
 
373
372
  <!-- A date picker, using the `select_date` helper from Rails
374
-
373
+
375
374
  ### Attributes
376
375
 
377
- - order: The order of the year, month and day menus. A comma separated string or an array. Default: "year, month, day"
378
-
379
- Any other attributes are passed through to the `select_date` helper.
376
+ - all the options of select_date and date_select are passed to the select_date Rails
377
+ helper
378
+
379
+ All the other attributes are passed to the `select_date` helper as the html-options hash.
380
380
 
381
381
  The menus default to the current date if the current value is nil.
382
-
382
+
383
+ Examples:
384
+
385
+ - override the input for date tag in a form
386
+ <my-special-date-view:>
387
+ <input start-year="&1940" order="day,month,year" />
388
+ </my-special-date-view:>
389
+
390
+ - override the tag application-wide
391
+ <extend tag='input' for='date'>
392
+ <old-input merge order="day,month,year" start-year="&1940" />
393
+ </extend>
394
+
383
395
  -->
384
- <def tag="input" for="date" attrs="order">
396
+ <def tag="input" for="date" attrs="use-month-numbers, use-short-month, add-month-numbers, use-month-names, date-separator, start-year, end-year, discard-day, discard-month, discard-year, order, include-blank, default, disabled, prompt, prefix">
385
397
  <% order = order.nil? ? [:year, :month, :day] : comma_split(order).*.to_sym -%>
386
- <%= select_date(this || current_time, attributes.merge(:prefix => param_name_for_this, :order => order)) %>
398
+ <%= select_date(this || current_time,
399
+ (all_attributes - attributes.keys).reverse_merge(:prefix => param_name_for_this).merge(:order => order),
400
+ attributes - [:name]) %>
387
401
  </def>
388
402
 
389
403
 
390
- <!-- A date/time picker, using the `select_date` helper from Rails
391
-
404
+ <!-- A date/time picker, using the `select_time` helper from Rails
405
+
392
406
  ### Attributes
393
407
 
394
- - order: The order of the year, month and date menus. A comma separated string or an array. Default: "year, month,
395
- day, hour, minute, second"
396
-
397
- Any other attributes are passed through to the `select_date` helper.
398
-
408
+ - include-seconds, time-separator, prompt and prefix are passed to the select_time helper as options
409
+
410
+ All the other attributes are passed to the `select_time` helper as the html-options hash.
411
+
399
412
  The menus default to the current time if the current value is nil.
400
-
413
+
401
414
  -->
402
- <def tag="input" for="time" attrs="order">
403
- <% order = order.nil? ? [:year, :month, :day, :hour, :minute, :second] : comma_split(order).*.to_sym -%>
404
- <%= select_date(this || current_time, attributes.merge(:prefix => param_name_for_this, :order => order)) %>
415
+ <def tag="input" for="time" attrs="include-seconds, time-separator, prompt, prefix">
416
+ <%= select_time( this || current_time,
417
+ (all_attributes - attributes.keys).reverse_merge(:prefix => param_name_for_this),
418
+ attributes - [:name] ) %>
405
419
  </def>
406
420
 
407
421
 
408
422
  <!-- A date/time picker, using the `select_datetime` helper from Rails
409
-
423
+
410
424
  ### Attributes
411
425
 
412
426
  - order: The order of the year, month and date menus. A comma separated string or an array. Default: "year, month,
413
427
  day, hour, minute"
414
-
415
- Any other attributes are passed through to the `select_datetime` helper.
416
-
428
+ - date-separator, discard-type, prompt and prefix are passed to the select_date helper as options
429
+
430
+ All the other attributes are passed to the `select_date` helper as the html-options hash.
431
+
417
432
  The menus default to the current time if the current value is nil.
418
433
 
419
434
  -->
420
- <def tag="input" for="datetime" attrs="order">
435
+ <def tag="input" for="datetime" attrs="order, date-separator, discard-type, prompt, prefix">
421
436
  <% if ! order.nil?
422
- order = comma_split(order).*.to_sym
437
+ order = comma_split(order).*.to_sym
423
438
  attributes.merge!(:order => order)
424
439
  end -%>
425
- <%= select_datetime(this || current_time, attributes.merge(:prefix => param_name_for_this)) %>
440
+ <%= select_datetime(this || current_time,
441
+ (all_attributes - attributes.keys).reverse_merge(:prefix => param_name_for_this).merge(:order => order),
442
+ attributes - [:name] ) %>
426
443
  </def>
427
444
 
428
445
  <!-- An `<input type='text'>` input. -->
@@ -446,7 +463,7 @@ The menus default to the current time if the current value is nil.
446
463
  </def>
447
464
 
448
465
  <!-- A `<select>` menu containing the values of an 'enum string'.
449
-
466
+
450
467
  ### Attributes
451
468
 
452
469
  - `labels` - A hash that gives custom labels for the values of the enum.
@@ -454,9 +471,9 @@ The menus default to the current time if the current value is nil.
454
471
  - `titleize` - Set to false to have the value itself (rather than `value.titleize`) be the default label. Default: true
455
472
  - `first-option` - a string to be used for an extra option in the first position. E.g. "Please choose..."
456
473
  - `first-value` - the value to be used with the `first-option`. Typically not used, meaning the option has a blank value.
457
-
474
+
458
475
  -->
459
- <def tag="input" for="HoboFields::EnumString" attrs="labels, titleize, first-option, first-value"><%
476
+ <def tag="input" for="HoboFields::Types::EnumString" attrs="labels, titleize, first-option, first-value"><%
460
477
  labels ||= {}
461
478
  labels = HashWithIndifferentAccess.new(labels)
462
479
  titleize = true if titleize.nil?
@@ -479,19 +496,19 @@ The URL that the call is POSTed to is the `object_url` of `this`, plus the metho
479
496
  `<remote-method-button>` supports all of the standard ajax attributes (see the main taglib documention for Rapid
480
497
  Forms). If any ajax attributes are given, the button becomes an ajax button, if not, Rails' `button_to` is used, which behaves similarly to a standard link.
481
498
 
482
- ### Attributes
499
+ ### Attributes
483
500
 
484
501
  - method: the name of the web-method to call
485
-
502
+
486
503
  - label: the label on the button
487
-
504
+
488
505
  -->
489
- <def tag="remote-method-button" attrs="method, update, label, confirm, url"><%=
490
- ajax_attributes, html_attributes = attributes.partition_hash(Hobo::RapidHelper::AJAX_ATTRS)
506
+ <def tag="remote-method-button" attrs="method, update, label, confirm, url"><%=
507
+ ajax_attributes, html_attributes = attributes.partition_hash(Hobo::Rapid::Helper::AJAX_ATTRS)
491
508
 
492
509
  url ||= object_url(this, method.to_s.gsub('-', '_'), :method => :post)
493
510
  raise ArgumentError, "no such web method '#{method}' on #{this.typed_id}" unless url
494
-
511
+
495
512
  add_classes!(html_attributes, "button remote-method-button #{method}-button")
496
513
  label ||= method.titleize
497
514
  if update || !ajax_attributes.empty?
@@ -504,10 +521,10 @@ Forms). If any ajax attributes are given, the button becomes an ajax button, if
504
521
  end
505
522
  %></def>
506
523
 
507
-
524
+
508
525
  <!-- Provides an ajax button to send a RESTful update or "PUT" to the server. i.e. to udate one or more fields of a
509
526
  record.
510
-
527
+
511
528
  Note that unlike simliar tags, `<update-button>` does not support both ajax and non-ajax modes at this time. It only
512
529
  does ajax.
513
530
 
@@ -515,23 +532,23 @@ does ajax.
515
532
 
516
533
  ### Attributes
517
534
 
518
- - label: The label on the button.
519
-
535
+ - label: The label on the button.
536
+
520
537
  - fields: A hash with new field values pairs to update the resource with. The items in the hash will be converted to
521
538
  HTTP parameters.
522
-
539
+
523
540
  - params: Another hash with additional HTTP parameters to include in the ajax request
524
-
541
+
525
542
  -->
526
543
  <def tag="update-button" attrs="label, update, fields, params"><%=
527
- raise HoboError.new("no update specified") unless update
544
+ raise Hobo::Error.new("no update specified") unless update
528
545
 
529
- ajax_attributes, html_attributes = attributes.partition_hash(Hobo::RapidHelper::AJAX_ATTRS)
546
+ ajax_attributes, html_attributes = attributes.partition_hash(Hobo::Rapid::Helper::AJAX_ATTRS)
530
547
  params = (params || {}).merge(this.class.name.underscore => fields)
531
548
  ajax_attributes.reverse_merge!(:message => label, :params => params, :method => :put)
532
549
  func = ajax_updater(object_url(this), update, ajax_attributes)
533
550
  html_attributes.reverse_merge!(:type =>'button', :onclick => func, :value => label)
534
-
551
+
535
552
  element :input, add_classes(html_attributes, "button update-button update-#{this.class.name.underscore}-button"), nil, true, true %>
536
553
  </def>
537
554
 
@@ -557,18 +574,18 @@ All the standard ajax attributes *except the callbacks* are supported (see the m
557
574
  ### Attributes
558
575
 
559
576
  - label: The label for the button. Default: "Remove"
560
-
577
+
561
578
  - in-place: delete in place (ajax)? Default: true, or false if the record to be deleted is the same as the top level
562
579
  context of the page
563
580
 
564
581
  - image: URL of an image for the button. Changes the rendered tag from `<input type='button'>` to `<input type='image'
565
582
  src='...'>`
566
-
583
+
567
584
  - fade: Perform the fade effect (true/false)? Default: true
568
-
585
+
569
586
  -->
570
587
  <def tag="delete-button" attrs="label, update, in-place, image, confirm, fade, subsite"><%=
571
- in_place = false if in_place.nil? && this == @this && request.method == :get
588
+ in_place = false if in_place.nil? && this == @this && request.method.downcase == "get"
572
589
  url = object_url(this, :method => :delete, :subsite => subsite)
573
590
  if (Dryml.last_if = url && can_delete?)
574
591
  attributes = attributes.merge(if image
@@ -576,9 +593,9 @@ All the standard ajax attributes *except the callbacks* are supported (see the m
576
593
  else
577
594
  { :type => "button" }
578
595
  end)
579
- label ||= ht("#{this.class.name.tableize}.actions.remove", :default=>"Remove")
580
- confirm = ht("hobo.messages.confirm", :default=>"Are you sure?") if confirm.nil?
581
-
596
+ label ||= t("hobo.actions.remove", :default=>"Remove")
597
+ confirm = t("hobo.messages.confirm", :default=>"Are you sure?") if confirm.nil?
598
+
582
599
  add_classes!(attributes,
583
600
  image ? "image-button" : "button",
584
601
  "delete-button delete-#{this.class.name.underscore.dasherize}-button")
@@ -601,7 +618,7 @@ All the standard ajax attributes *except the callbacks* are supported (see the m
601
618
 
602
619
 
603
620
  <!-- Provides an ajax create button that will send a RESTful "POST" to the server to create a new resource.
604
-
621
+
605
622
  All of the standard ajax attributes are supported (see the main taglib documention for Rapid Forms).
606
623
 
607
624
  ### Attributes
@@ -610,7 +627,7 @@ All of the standard ajax attributes are supported (see the main taglib documenti
610
627
 
611
628
  -->
612
629
  <def tag="create-button" attrs="model, update, label, fields, message"><%=
613
- raise HoboError.new("no update specified") unless update
630
+ raise Hobo::Error.new("no update specified") unless update
614
631
 
615
632
  fields ||= {}
616
633
  class_or_assoc = if model
@@ -619,12 +636,12 @@ All of the standard ajax attributes are supported (see the main taglib documenti
619
636
  fields[this_field_reflection.primary_key_name] = this.proxy_owner.id
620
637
  this
621
638
  else
622
- raise HoboError.new("invalid context for <create-button>")
639
+ raise Hobo::Error.new("invalid context for <create-button>")
623
640
  end
624
641
  new = class_or_assoc.new(fields)
625
642
  new.set_creator(current_user)
626
643
  if can_create?(new)
627
- label ||= ht("#{new.class.name.tableize}.actions.new", :default=>"New #{new.class.name.titleize}")
644
+ label ||= ht("#{new.class.to_s.underscore}.actions.new", :default=>"New #{new.class.model_name.human}")
628
645
  ajax_attributes = { :message => message }
629
646
  class_name = new.class.name.underscore
630
647
  ajax_attributes[:params] = { class_name => fields } unless fields.empty?
@@ -646,27 +663,27 @@ This is the default input that Rapid uses for `belongs_to` associations. The men
646
663
  - `options` - an array of records to include in the menu. Defaults to the all the records in the target table that match any `:conditions` declared on the `belongs_to` (subject to `limit`)
647
664
  - `limit` - if `options` is not specified, this limits the number of records. Default: 100
648
665
  - `text_method` - The method to call on each record to get the text for the option. Multiple methods are supported ie "institution.name"
649
-
666
+
650
667
  ### See Also
651
668
 
652
669
  For situations where there are too many target records to practically include in a menu, `<name-one>` provides an autocompleter which would be more suitable.
653
670
 
654
671
  -->
655
672
  <def tag="select-one" attrs="include-none, blank-message, options, sort, limit, text-method"><%
656
- raise Hobo::PermissionDeniedError.new("Not allowed to edit #{this_field}") if !attributes[:disabled] && !can_edit?
657
-
658
- blank_message ||= ht("#{this_type.name.tableize}.message.none", :default=>"(No #{this_type.view_hints.model_name})")
673
+ raise Hobo::PermissionDeniedError.new("Not allowed to edit #{this_field}") if !attributes[:disabled] && !can_edit?
674
+ blank_message ||= ht("#{this_type.name.underscore}.messages.none", :default=>"No #{this_type.model_name.human} available.")
659
675
  limit ||= 100
660
-
676
+
661
677
  options ||= begin
662
- conditions = ActiveRecord::Associations::BelongsToAssociation.new(this_parent, this_field_reflection).conditions
663
- this_field_reflection.klass.all(:conditions => conditions, :limit => limit).select {|x| can_view?(x)}
678
+ conditions = ActiveRecord::Associations::BelongsToAssociation.new(this_parent, this_field_reflection).send(:conditions)
679
+ order = this_field_reflection.klass.default_order
680
+ this_field_reflection.klass.all(:conditions => conditions, :limit => limit, :order => order).select {|x| can_view?(x)}
664
681
  end
665
682
 
666
683
  if text_method.nil?
667
684
  select_options = options.map { |x| [x.to_s, x.id] }
668
685
  else
669
- select_options = options.map do |x|
686
+ select_options = options.map do |x|
670
687
  [ text_method.split(".").inject(x) { |v, method| v.send(method) },
671
688
  x.id ]
672
689
  end
@@ -747,7 +764,7 @@ If you wish to set `min-chars` to 0, you will require this [patch to controls.js
747
764
  min_chars ||= 1
748
765
  value = name(:no_wrapper => true, :if_present => true)
749
766
  -%>
750
- <input type="text" name="#{param_name_for_this}"
767
+ <input type="text" name="#{param_name_for_this}"
751
768
  class="autocompleter #{type_and_field._?.dasherize} #{css_data :complete_on, typed_id(complete_target), completer} #{css_data :min_chars, min_chars} #{'nil-value' if value==''}"
752
769
  value="#{value=='' ? nil_value : value}"
753
770
  merge-attrs/>
@@ -758,15 +775,15 @@ If you wish to set `min-chars` to 0, you will require this [patch to controls.js
758
775
  <!-- nodoc. -->
759
776
  <def tag="sti-type-input">
760
777
  <select name="#{param_name_for(form_field_path + ['type'])}">
761
- <%= options_for_select(this.class.send(:subclasses).map{|x| [x.name.titleize, x.name]}, this.class.name) %>
778
+ <%= options_for_select(this.class.send(:descendants).map{|x| [x.name.titleize, x.name]}, this.class.name) %>
762
779
  </select>
763
780
  </def>
764
781
 
765
782
 
766
783
  <!-- A `<select>` menu input. This tag differes from `<select-menu>` only in that it adds the correct `name` attribute for the current field, and `selected` default to `this`.
767
-
784
+
768
785
  ### Attributes
769
-
786
+
770
787
  - `options` - an array of options suitable to be passed to the Rails `options_for_select` helper.
771
788
  - `selected` - the value (from the `options` array) that should be initially selected. Defaults to `this`
772
789
  - `first-option` - a string to be used for an extra option in the first position. E.g. "Please choose..."
@@ -778,14 +795,23 @@ If you wish to set `min-chars` to 0, you will require this [patch to controls.js
778
795
  </def>
779
796
 
780
797
 
781
- <!-- Renders a readable list of error messages following a form submission. Expects the errors to be in `this.errors`. Renders nothing if there are no errors.
798
+ <!-- Renders a localized list of error messages following a form submission. Expects the errors to be in `this.errors`. Renders nothing if there are no errors.
782
799
  -->
783
800
  <def tag="error-messages">
784
- <section class="error-messages" merge-attrs if="&this.errors.length > 0">
785
- <h2 param="heading"><ht key="hobo.messages.error_correct_following">To proceed please correct the following:</ht></h2>
801
+ <section class="error-messages" merge-attrs if="&this.errors.size > 0">
802
+ <h2 param="heading">
803
+ <t key="activerecord.errors.template.header" model="&this.class.model_name.human" count="&this.errors.size">
804
+ <%= model = this.class.model_name.human
805
+ count = this.errors.size
806
+ count==1 ? "1 error prohibited this #{model} from being saved" :
807
+ "#{count} errors prohibited this #{model} from being saved"
808
+ %>
809
+ </t>
810
+ </h2>
811
+ <t key="activerecord.errors.template.body">There were problems with the following fields:</t>
786
812
  <ul param>
787
- <% this.errors.each do |attr, message|; next if message == "..." -%>
788
- <li param><%= this.class.view_hints.field_name(attr) unless attr.to_s == 'base' %> <%= message %></li>
813
+ <% this.errors.to_a.each do |message| -%>
814
+ <li param><%= message %></li>
789
815
  <% end -%>
790
816
  </ul>
791
817
  </section>
@@ -794,16 +820,16 @@ If you wish to set `min-chars` to 0, you will require this [patch to controls.js
794
820
 
795
821
  <!--
796
822
  An input for `has_many :through` associations that lets the user chose the items from a `<select>` menu.
797
-
798
- To use this tag, the model of the items the user is chosing *must* have unique names, and the
823
+
824
+ To use this tag, the model of the items the user is chosing *must* have unique names, and the
799
825
  -->
800
826
  <def tag="select-many" attrs="options, targets, remove-label, prompt, disabled, name"><%
801
- prompt ||= ht("#{this.name.tableize}.message.none", :default=>"Add #{this.view_hints.model_name}")
802
- options ||= this_field_reflection.klass.all(:conditions =>this.conditions).select {|x| can_view?(x)}
827
+ prompt ||= ht("#{this_field_reflection.klass.to_s.underscore}.form.select_many.prompt", :default=>"Add #{this_field.titleize.singularize}")
828
+ options ||= this_field_reflection.klass.all(:conditions =>this.send(:conditions)).select {|x| can_view?(x)}
803
829
  name ||= param_name_for_this
804
-
830
+
805
831
  values = this
806
- remove_label ||= ht("#{this.name.tableize}.actions.remove", :default=>'Remove')
832
+ remove_label ||= t("hobo.actions.remove", :default=>'Remove')
807
833
  -%>
808
834
  <div class="input select-many" merge-attrs>
809
835
  <div style="display:none" class="item-proto">
@@ -863,7 +889,7 @@ Use the `uri` option to specify a redirect location:
863
889
  ...
864
890
  </form>
865
891
  -->
866
- <def tag="after-submit" attrs="uri, stay-here, go-back"><%
892
+ <def tag="after-submit" attrs="uri, stay-here, go-back"><%
867
893
  uri = "stay-here" if stay_here
868
894
  uri = session[:previous_uri] if go_back
869
895
  -%>
@@ -872,16 +898,22 @@ Use the `uri` option to specify a redirect location:
872
898
 
873
899
 
874
900
  <!-- A simple wrapper around the `<select>` tag and `options_for_select` helper
875
-
901
+
876
902
  ### Attributes
877
903
 
878
904
  - `options` - an array of options suitable to be passed to the Rails `options_for_select` helper.
879
905
  - `selected` - the value (from the `options` array) that should be initially selected. Defaults to `this`
880
906
  - `first-option` - a string to be used for an extra option in the first position. E.g. "Please choose..."
881
907
  - `first-value` - the value to be used with the `first-option`. Typically not used, meaning the option has a blank value.
882
-
908
+ - `key` - the key used to lookup in the locale file or 'default' by default. If you pass it hobo will lookup in the namespace "tags.select_menu.#{key}" in order to find `options`, `first_option` and `first_value`. The passed attributes are used as a default in case the lookups fail. (see the documentation of filter-menu tag for a similar example).
883
909
  -->
884
- <def tag="select-menu" attrs="options, selected, first-option, first-value">
910
+ <def tag="select-menu" attrs="options, selected, first-option, first-value, key">
911
+ <% key ||= 'default'
912
+ %w[options first_option first_value].each do |a|
913
+ str = t("tags.select_menu.#{key}.#{a}", :default=>'')
914
+ eval "#{a} = str unless str.blank?"
915
+ end
916
+ -%>
885
917
  <select merge-attrs param="default">
886
918
  <% selected=this if selected.nil? %>
887
919
  <option value="#{first_value}" unless="&first_option.nil?"><first-option/></option>
@@ -898,16 +930,16 @@ Use the `uri` option to specify a redirect location:
898
930
  - `disabled` - if true, sets the disabled flag on all check boxes.
899
931
 
900
932
  -->
901
- <def tag="check-many" attrs="options, disabled"><%
933
+ <def tag="check-many" attrs="options, disabled"><%
902
934
  collection = this
903
935
  param_name = param_name_for_this
904
936
  options ||= begin
905
- conditions = ActiveRecord::Associations::BelongsToAssociation.new(this_parent, this_field_reflection).conditions
937
+ conditions = ActiveRecord::Associations::BelongsToAssociation.new(this_parent, this_field_reflection).send(:conditions)
906
938
  this_field_reflection.klass.all(:conditions => conditions, :limit => 100).select {|x| can_view?(x)}
907
939
  end
908
940
  -%>
909
941
  <ul class="check-many" param="default" merge-attrs>
910
- <input type="hidden" name="#{param_name}[]" value=""/><% # ensure all items are removed when nothing checked
942
+ <input type="hidden" name="#{param_name}[]" value=""/><% # ensure all items are removed when nothing checked
911
943
  %>
912
944
  <li repeat="&options" param>
913
945
  <input type="checkbox" name="#{param_name}[]" value="@#{this.id}" checked="&this.in?(collection)" disabled="&disabled"/>
@@ -924,17 +956,17 @@ Use the `uri` option to specify a redirect location:
924
956
 
925
957
 
926
958
  <!-- Creates a sub-section of the form which the user can repeat using (+) and (-) buttons, in order to allow an entire `has_many` collection to be created/edited in a single form.
927
-
959
+
928
960
  This tag is very different from tags like `<select-many>` and `<check-many>` in that:
929
961
 
930
962
  - Those tags are used to *choose existing records* to include in the association, while `<input-many>` is used to actually create or edit the records in the association.
931
-
963
+
932
964
  ### Example
933
965
 
934
966
  Say you are creating a new `Category` in your online shop, and you want to create some initial products *in the same form*, you can add the following to your form:
935
967
 
936
968
  <input-many:products><field-list fields="name, price"/></input-many>
937
-
969
+
938
970
  The body of the tag will be repeated for each of the current records in the collection, or will just appear once (with blank fields) if the colleciton is empty.
939
971
 
940
972
  ### Attributes
@@ -942,13 +974,13 @@ The body of the tag will be repeated for each of the current records in the coll
942
974
  - fields: If you do not specify any content for the input-many, a `<field-list>` is rendered. This attribute is passed through to the `<field-list>`
943
975
 
944
976
  - skip: Passed through to the `<field-list>`. If not specified, it defaults to the parent association.
945
-
977
+
946
978
  ### Example
947
979
 
948
980
  Say you are creating a new `Category` in your online shop, and you want to create some initial products *in the same form*, you can add the following to your form:
949
981
 
950
982
  <hjq-input-many:products fields="name, price" />
951
-
983
+
952
984
  You'll often want to provide the `item` parameter:
953
985
 
954
986
  <hjq-input-many:products><item:><field-list fields="name, price" /></item:></hjq-input-many>
@@ -1021,7 +1053,7 @@ end
1021
1053
  <input type="hidden" class="empty-input" id="#{underize param_name_for_this}" name="#{param_name_for_this}" value="" disabled="&(!this.empty? || minimum>0)" />
1022
1054
  <fake-field-context fake-field="-1" context="&template">
1023
1055
  <div param="empty-message">
1024
- <ht key="#{this.class.name.tableize}.collection.empty_message">
1056
+ <ht key="#{this.class.to_s.underscore}.collection.empty_message">
1025
1057
  No <%= this.class.name.titleize.downcase.pluralize %>.
1026
1058
  </ht>
1027
1059
  </div>
@@ -1029,7 +1061,7 @@ end
1029
1061
  <button param="remove-item" class="hidden" id="#{underize param_name_for_this}_remove">-</button>
1030
1062
  <button param="add-item" id="#{underize param_name_for_this}_add">+</button>
1031
1063
  </div>
1032
- </fake-field-context>
1064
+ </fake-field-context>
1033
1065
  </li>
1034
1066
  <fake-field-context fake-field="0" context="&template">
1035
1067
  <li class="input-many-li" if="&(this_parent.empty? && minimum>0)" id="#{underize param_name_for_this}">
@@ -1041,7 +1073,7 @@ end
1041
1073
  <button param="add-item" id="#{underize param_name_for_this}_add">+</button>
1042
1074
  </div>
1043
1075
  </li>
1044
- </fake-field-context>
1076
+ </fake-field-context>
1045
1077
  <li repeat class="input-many-li #{'record-with-errors' unless this.errors.empty?}" id="#{underize param_name_for_this}">
1046
1078
  <error-messages without-heading class="sub-record"/>
1047
1079
  <hidden-id-field/>
@@ -1106,8 +1138,8 @@ The specified sort order may be maintained even without `acts_as_list`. The ite
1106
1138
  <!-- Renders the common "or (Cancel)" for a form. Attributes are merged into the link (`<a>Cancel</a>`), making it easy to customise the destination of the cancel link. By default it will link to `this` or `this.class`.
1107
1139
  -->
1108
1140
  <def tag="or-cancel">
1109
- <if test="&linkable?"><ht key="hobo.support.or">or</ht> <a merge-attrs><ht key="hobo.actions.cancel">Cancel</ht></a></if>
1141
+ <if test="&linkable?"><t key="hobo.support.or">or</t> <a merge-attrs><t key="hobo.actions.cancel">Cancel</t></a></if>
1110
1142
  <else>
1111
- <if test="&linkable?(this.class)"><ht key="hobo.support.or">or</ht> <a to="&this.class" merge-attrs><ht key="hobo.actions.cancel">Cancel</ht></a></if>
1143
+ <if test="&linkable?(this.class)"><t key="hobo.support.or">or</t> <a to="&this.class" merge-attrs><t key="hobo.actions.cancel">Cancel</t></a></if>
1112
1144
  </else>
1113
1145
  </def>