card 1.17.4 → 1.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (389) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/card.gemspec +24 -25
  4. data/config/initializers/01_init_ruby_extensions.rb +0 -4
  5. data/config/initializers/inflections.rb +1 -1
  6. data/config/initializers/notification.rb +2 -2
  7. data/db/migrate/20110511221913_require_earlier_migrations.rb +3 -3
  8. data/db/migrate/20120105203350_require_1_8_migrations.rb +3 -3
  9. data/db/migrate/20121111025347_require_1_10_migrations.rb +3 -3
  10. data/db/migrate/20130106052640_table_cleanup.rb +4 -4
  11. data/db/migrate/20130411210957_update_codenames.rb +2 -2
  12. data/db/migrate/20141001105348_move_revisions_to_actions.rb +4 -4
  13. data/db/migrate/20141121172918_rename_card_migration_table.rb +2 -2
  14. data/db/migrate/20141208132159_remove_present_from_reference_table.rb +2 -2
  15. data/db/migrate/20141216053032_better_index_names.rb +9 -9
  16. data/db/migrate_core_cards/20120611203506_rails_inflection_updates.rb +29 -32
  17. data/db/migrate_core_cards/20130411191151_renaming_for_menu.rb +3 -4
  18. data/db/migrate_core_cards/20130411211600_delete_old_related_tab_cards.rb +1 -1
  19. data/db/migrate_core_cards/20130419215612_import_help_text.rb +1 -2
  20. data/db/migrate_core_cards/20130823192433_add_style_cards.rb +3 -3
  21. data/db/migrate_core_cards/20130910183318_move_styles_to_content.rb +2 -3
  22. data/db/migrate_core_cards/20130920214038_jsonize_tinymce.rb +2 -2
  23. data/db/migrate_core_cards/20130920291703_update_stylesheets.rb +1 -2
  24. data/db/migrate_core_cards/20130927191728_account_events.rb +5 -6
  25. data/db/migrate_core_cards/20131016172445_common_css_patch.rb +2 -3
  26. data/db/migrate_core_cards/20140110193325_reset_account_request_type.rb +0 -1
  27. data/db/migrate_core_cards/20140307231621_user_data_to_cards.rb +23 -32
  28. data/db/migrate_core_cards/20140317035504_account_requests_to_signups.rb +1 -7
  29. data/db/migrate_core_cards/20140512155840_add_script_cards.rb +21 -24
  30. data/db/migrate_core_cards/20140629222005_add_email_cards.rb +17 -22
  31. data/db/migrate_core_cards/20140725180118_config_card_updates.rb +2 -2
  32. data/db/migrate_core_cards/20141111083921_delete_machine_output.rb +1 -3
  33. data/db/migrate_core_cards/20141115034214_config_descriptions_etc.rb +2 -2
  34. data/db/migrate_core_cards/20141119001955_make_symlinks_relative.rb +3 -3
  35. data/db/migrate_core_cards/20141120120605_fix_notification_html_message.rb +1 -1
  36. data/db/migrate_core_cards/20141204061304_watchers_to_following.rb +8 -12
  37. data/db/migrate_core_cards/20141208162106_add_ace_script.rb +2 -3
  38. data/db/migrate_core_cards/20141216155251_add_more_following_cards.rb +10 -10
  39. data/db/migrate_core_cards/20150202143810_import_bootstrap_layout.rb +10 -12
  40. data/db/migrate_core_cards/20150220134731_following_to_follow_rule.rb +4 -4
  41. data/db/migrate_core_cards/20150317162412_bootstrap_themes.rb +3 -3
  42. data/db/migrate_core_cards/20150326205655_bootswatch_themes.rb +7 -7
  43. data/db/migrate_core_cards/20150429090551_search_card_context.rb +18 -20
  44. data/db/migrate_core_cards/20150508212032_menu_compatibility.rb +3 -7
  45. data/db/migrate_core_cards/20150510031118_fix_skin_images.rb +2 -3
  46. data/db/migrate_core_cards/20150528084659_add_session_cardtype.rb +3 -3
  47. data/db/migrate_core_cards/20150601133433_add_recent_setting_session_card.rb +4 -4
  48. data/db/migrate_core_cards/20150610171702_add_debugger_session_card.rb +4 -4
  49. data/db/migrate_core_cards/20150610180019_add_recaptcha_key_and_admin_info_cards.rb +5 -11
  50. data/db/migrate_core_cards/20150724123438_update_file_and_image_cards.rb +29 -35
  51. data/db/migrate_core_cards/20150824135418_update_file_history.rb +10 -14
  52. data/db/migrate_core_cards/20150903130006_attachment_upload_cards.rb +1 -1
  53. data/db/schema.rb +92 -94
  54. data/db/seed/new/card_actions.yml +461 -469
  55. data/db/seed/new/card_acts.yml +154 -172
  56. data/db/seed/new/card_changes.yml +4076 -4031
  57. data/db/seed/new/card_references.yml +1584 -1927
  58. data/db/seed/new/cards.yml +2095 -2112
  59. data/db/seed/test/fixtures/card_actions.yml +1497 -1505
  60. data/db/seed/test/fixtures/card_acts.yml +454 -472
  61. data/db/seed/test/fixtures/card_changes.yml +7309 -7263
  62. data/db/seed/test/fixtures/card_references.yml +2263 -2613
  63. data/db/seed/test/fixtures/cards.yml +3298 -3316
  64. data/db/seed/test/seed.rb +3 -0
  65. data/lib/card.rb +17 -9
  66. data/lib/card/active_record_ext.rb +6 -8
  67. data/lib/card/active_record_helper.rb +42 -32
  68. data/lib/card/auth.rb +3 -3
  69. data/lib/card/cache.rb +4 -4
  70. data/lib/card/cache/persistent.rb +9 -5
  71. data/lib/card/cache/temporary.rb +5 -5
  72. data/lib/card/chunk.rb +1 -1
  73. data/lib/card/codename.rb +3 -2
  74. data/lib/card/content.rb +62 -57
  75. data/lib/card/core_ext.rb +20 -30
  76. data/lib/card/diff.rb +88 -76
  77. data/lib/card/director_register.rb +66 -0
  78. data/lib/card/env.rb +14 -17
  79. data/lib/card/exceptions.rb +7 -9
  80. data/lib/card/format.rb +18 -367
  81. data/lib/card/format/nest.rb +183 -0
  82. data/lib/card/format/permission.rb +63 -0
  83. data/lib/card/format/render.rb +140 -0
  84. data/lib/card/loader.rb +17 -26
  85. data/lib/card/location.rb +6 -6
  86. data/lib/card/mailer.rb +4 -7
  87. data/lib/card/migration.rb +1 -1
  88. data/lib/card/name.rb +3 -6
  89. data/lib/card/query.rb +8 -8
  90. data/lib/card/query/attributes.rb +6 -6
  91. data/lib/card/query/clause.rb +10 -10
  92. data/lib/card/query/join.rb +7 -9
  93. data/lib/card/query/reference.rb +17 -19
  94. data/lib/card/query/sql_statement.rb +2 -2
  95. data/lib/card/query/value.rb +15 -16
  96. data/lib/card/set.rb +106 -209
  97. data/lib/card/set/event.rb +126 -0
  98. data/lib/card/set_pattern.rb +42 -29
  99. data/lib/card/simplecov_helper.rb +19 -19
  100. data/lib/card/spec_helper.rb +40 -16
  101. data/lib/card/stage.rb +72 -0
  102. data/lib/card/stage_director.rb +231 -0
  103. data/lib/card/subcards.rb +56 -24
  104. data/lib/card/subdirector_array.rb +31 -0
  105. data/lib/card/success.rb +15 -18
  106. data/lib/card/version.rb +1 -2
  107. data/lib/card/view_cache.rb +4 -4
  108. data/lib/card/view_name.rb +10 -8
  109. data/lib/cardio.rb +1 -1
  110. data/lib/generators/card.rb +2 -4
  111. data/lib/generators/card/format/format_generator.rb +4 -4
  112. data/lib/generators/card/migration/migration_generator.rb +6 -6
  113. data/lib/generators/card/set/set_generator.rb +5 -6
  114. data/mod/01_core/chunk/include.rb +2 -1
  115. data/mod/01_core/chunk/link.rb +2 -2
  116. data/mod/01_core/chunk/literal.rb +6 -9
  117. data/mod/01_core/chunk/query_reference.rb +1 -1
  118. data/mod/01_core/chunk/reference.rb +2 -2
  119. data/mod/01_core/chunk/uri.rb +52 -63
  120. data/mod/01_core/format/html_format.rb +8 -12
  121. data/mod/01_core/format/text_format.rb +1 -1
  122. data/mod/01_core/set/all/actify.rb +96 -0
  123. data/mod/01_core/set/all/active_card.rb +7 -7
  124. data/mod/01_core/set/all/collection.rb +19 -20
  125. data/mod/01_core/set/all/content.rb +9 -7
  126. data/mod/01_core/set/all/erb.rb +5 -5
  127. data/mod/01_core/set/all/event.rb +60 -0
  128. data/mod/01_core/set/all/fetch.rb +13 -19
  129. data/mod/01_core/set/all/haml.rb +1 -1
  130. data/mod/01_core/set/all/initialize.rb +35 -41
  131. data/mod/01_core/set/all/location_history.rb +3 -5
  132. data/mod/01_core/set/all/name.rb +19 -68
  133. data/mod/01_core/set/all/name_validations.rb +56 -0
  134. data/mod/01_core/set/all/pattern.rb +2 -2
  135. data/mod/01_core/set/all/permissions.rb +14 -20
  136. data/mod/01_core/set/all/phases.rb +9 -200
  137. data/mod/01_core/set/all/references.rb +10 -10
  138. data/mod/01_core/set/all/rules.rb +3 -4
  139. data/mod/01_core/set/all/stages.rb +24 -0
  140. data/mod/01_core/set/all/states.rb +4 -4
  141. data/mod/01_core/set/all/subcards.rb +16 -26
  142. data/mod/01_core/set/all/templating.rb +1 -3
  143. data/mod/01_core/set/all/tracked_attributes.rb +47 -48
  144. data/mod/01_core/set/all/trash.rb +10 -10
  145. data/mod/01_core/set/all/type.rb +9 -8
  146. data/mod/01_core/set/all/utils.rb +10 -14
  147. data/mod/01_core/set/all/view_cache.rb +2 -2
  148. data/mod/01_core/set_pattern/01_all.rb +3 -3
  149. data/mod/01_core/set_pattern/02_all_plus.rb +3 -3
  150. data/mod/01_core/set_pattern/03_type.rb +2 -2
  151. data/mod/01_core/set_pattern/04_star.rb +3 -3
  152. data/mod/01_core/set_pattern/05_rstar.rb +3 -3
  153. data/mod/01_core/set_pattern/06_right.rb +2 -2
  154. data/mod/01_core/set_pattern/07_type_plus_right.rb +2 -2
  155. data/mod/01_core/set_pattern/08_self.rb +1 -1
  156. data/mod/01_core/spec/chunk/literal_spec.rb +7 -8
  157. data/mod/01_core/spec/chunk/uri_spec.rb +140 -142
  158. data/mod/01_core/spec/format/html_format_spec.rb +72 -57
  159. data/mod/01_core/spec/set/all/collection_spec.rb +63 -43
  160. data/mod/01_core/spec/set/all/content_spec.rb +4 -4
  161. data/mod/01_core/spec/set/all/fetch_spec.rb +12 -3
  162. data/mod/01_core/spec/set/all/name_spec.rb +3 -4
  163. data/mod/01_core/spec/set/all/pattern_spec.rb +32 -35
  164. data/mod/01_core/spec/set/all/permissions_spec.rb +17 -5
  165. data/mod/01_core/spec/set/all/phases_spec.rb +0 -1
  166. data/mod/01_core/spec/set/all/references_spec.rb +1 -1
  167. data/mod/01_core/spec/set/all/rules2_spec.rb +79 -91
  168. data/mod/01_core/spec/set/all/rules_spec.rb +63 -56
  169. data/mod/01_core/spec/set/all/templating_spec.rb +0 -1
  170. data/mod/01_core/spec/set/all/tracked_attributes_spec.rb +4 -5
  171. data/mod/01_core/spec/set/all/trash_spec.rb +23 -1
  172. data/mod/01_core/spec/set/all/type_spec.rb +2 -5
  173. data/mod/01_history/lib/card/action.rb +8 -10
  174. data/mod/01_history/set/all/actions.rb +2 -4
  175. data/mod/01_history/set/all/content_history.rb +38 -32
  176. data/mod/01_history/set/all/history.rb +20 -17
  177. data/mod/02_basic_types/format/rss_format.rb +0 -1
  178. data/mod/02_basic_types/set/all/all_css.rb +9 -13
  179. data/mod/02_basic_types/set/all/all_csv.rb +14 -17
  180. data/mod/02_basic_types/set/all/all_js.rb +3 -4
  181. data/mod/02_basic_types/set/all/base.rb +2 -2
  182. data/mod/02_basic_types/set/all/file.rb +2 -5
  183. data/mod/02_basic_types/set/all/json.rb +19 -18
  184. data/mod/02_basic_types/set/all/rss.rb +3 -3
  185. data/mod/02_basic_types/set/all/text.rb +1 -3
  186. data/mod/02_basic_types/set/type/html.rb +4 -8
  187. data/mod/02_basic_types/set/type/plain_text.rb +2 -3
  188. data/mod/02_basic_types/set/type/pointer.rb +82 -92
  189. data/mod/02_basic_types/spec/set/all/all_css_spec.rb +2 -2
  190. data/mod/02_basic_types/spec/set/all/all_csv_spec.rb +6 -4
  191. data/mod/02_basic_types/spec/set/all/base_spec.rb +6 -6
  192. data/mod/02_basic_types/spec/set/all/json_spec.rb +8 -8
  193. data/mod/02_basic_types/spec/set/type/plain_text_spec.rb +3 -3
  194. data/mod/02_basic_types/spec/set/type/pointer_spec.rb +29 -32
  195. data/mod/03_machines/lib/card/machine.rb +95 -81
  196. data/mod/03_machines/lib/card/machine_input.rb +35 -34
  197. data/mod/03_machines/set/right/machine_input.rb +1 -1
  198. data/mod/03_machines/set/self/script_ace.rb +2 -3
  199. data/mod/03_machines/set/self/script_card_menu.rb +2 -3
  200. data/mod/03_machines/set/self/script_jquery_helper.rb +2 -2
  201. data/mod/03_machines/set/self/script_slot.rb +2 -2
  202. data/mod/03_machines/set/self/style_bootstrap_compatible.rb +1 -1
  203. data/mod/03_machines/set/self/style_cards.rb +1 -1
  204. data/mod/03_machines/set/self/style_jquery_ui_smoothness.rb +0 -1
  205. data/mod/03_machines/set/type/coffee_script.rb +9 -13
  206. data/mod/03_machines/set/type/css.rb +12 -13
  207. data/mod/03_machines/set/type/java_script.rb +6 -8
  208. data/mod/03_machines/set/type/scss.rb +4 -5
  209. data/mod/03_machines/set/type/skin.rb +3 -6
  210. data/mod/03_machines/spec/lib/shared_machine_examples.rb +31 -38
  211. data/mod/03_machines/spec/lib/shared_machine_input_examples.rb +7 -8
  212. data/mod/03_machines/spec/set/type/coffeescript_spec.rb +19 -13
  213. data/mod/03_machines/spec/set/type/css_spec.rb +22 -16
  214. data/mod/03_machines/spec/set/type/scss_spec.rb +28 -21
  215. data/mod/03_machines/spec/set/type/skin_spec.rb +28 -30
  216. data/mod/04_settings/lib/card/setting.rb +4 -4
  217. data/mod/04_settings/set/abstract/permission.rb +30 -37
  218. data/mod/04_settings/set/right/add_help.rb +3 -3
  219. data/mod/04_settings/set/right/script.rb +4 -5
  220. data/mod/04_settings/set/right/structure.rb +3 -4
  221. data/mod/04_settings/set/right/style.rb +3 -3
  222. data/mod/04_settings/set/self/add_help.rb +1 -1
  223. data/mod/04_settings/set/self/input.rb +1 -1
  224. data/mod/04_settings/set/self/on_create.rb +1 -1
  225. data/mod/04_settings/set/self/options.rb +1 -1
  226. data/mod/04_settings/set/self/options_label.rb +1 -1
  227. data/mod/04_settings/set/type/setting.rb +29 -44
  228. data/mod/04_settings/spec/set/right/comment_spec.rb +9 -12
  229. data/mod/04_settings/spec/set/right/script_spec.rb +7 -7
  230. data/mod/04_settings/spec/set/right/structure_spec.rb +13 -12
  231. data/mod/04_settings/spec/set/right/style_spec.rb +13 -13
  232. data/mod/04_settings/spec/set/type/setting_spec.rb +1 -1
  233. data/mod/05_email/format/email_html_format.rb +1 -1
  234. data/mod/05_email/format/email_text_format.rb +2 -2
  235. data/mod/05_email/lib/card/follow_option.rb +12 -15
  236. data/mod/05_email/set/all/email_html.rb +2 -3
  237. data/mod/05_email/set/all/email_text.rb +3 -3
  238. data/mod/05_email/set/all/follow.rb +14 -22
  239. data/mod/05_email/set/all/notify.rb +11 -11
  240. data/mod/05_email/set/all/observer.rb +7 -8
  241. data/mod/05_email/set/right/bcc.rb +4 -9
  242. data/mod/05_email/set/right/follow.rb +26 -39
  243. data/mod/05_email/set/right/follow_fields.rb +2 -2
  244. data/mod/05_email/set/right/followers.rb +3 -1
  245. data/mod/05_email/set/right/following.rb +13 -16
  246. data/mod/05_email/set/self/always.rb +1 -2
  247. data/mod/05_email/set/self/created.rb +4 -6
  248. data/mod/05_email/set/self/edited.rb +3 -7
  249. data/mod/05_email/set/self/follow_defaults.rb +11 -12
  250. data/mod/05_email/set/self/never.rb +2 -4
  251. data/mod/05_email/set/type/email_template.rb +40 -27
  252. data/mod/05_email/set/type_plus_right/user/follow.rb +159 -157
  253. data/mod/05_email/spec/set/all/follow_spec.rb +28 -37
  254. data/mod/05_email/spec/set/all/notify_spec.rb +21 -26
  255. data/mod/05_email/spec/set/all/observer_spec.rb +58 -37
  256. data/mod/05_email/spec/set/right/followers_spec.rb +9 -14
  257. data/mod/05_email/spec/set/right/following_spec.rb +1 -1
  258. data/mod/05_email/spec/set/self/follow_defaults_spec.rb +1 -1
  259. data/mod/05_standard/lib/carrier_wave/cardmount.rb +9 -9
  260. data/mod/05_standard/lib/file_uploader.rb +8 -13
  261. data/mod/05_standard/lib/image_uploader.rb +8 -9
  262. data/mod/05_standard/set/abstract/attachment.rb +26 -43
  263. data/mod/05_standard/set/all/account.rb +2 -2
  264. data/mod/05_standard/set/all/comment.rb +11 -13
  265. data/mod/05_standard/set/all/error.rb +18 -18
  266. data/mod/05_standard/set/all/event_viz.rb +16 -29
  267. data/mod/05_standard/set/all/links.rb +35 -34
  268. data/mod/05_standard/set/all/list_changes.rb +10 -12
  269. data/mod/05_standard/set/all/rich_html/content.rb +13 -13
  270. data/mod/05_standard/set/all/rich_html/editing.rb +5 -5
  271. data/mod/05_standard/set/all/rich_html/form.rb +22 -26
  272. data/mod/05_standard/set/all/rich_html/header.rb +18 -25
  273. data/mod/05_standard/set/all/rich_html/menu.rb +20 -22
  274. data/mod/05_standard/set/all/rich_html/modal.rb +3 -3
  275. data/mod/05_standard/set/all/rich_html/toolbar.rb +49 -58
  276. data/mod/05_standard/set/all/rich_html/wrapper.rb +40 -41
  277. data/mod/05_standard/set/right/account.rb +26 -14
  278. data/mod/05_standard/set/right/email.rb +2 -2
  279. data/mod/05_standard/set/right/password.rb +6 -5
  280. data/mod/05_standard/set/right/salt.rb +2 -2
  281. data/mod/05_standard/set/right/stats.rb +17 -20
  282. data/mod/05_standard/set/right/token.rb +1 -1
  283. data/mod/05_standard/set/right/when_created.rb +1 -1
  284. data/mod/05_standard/set/right/when_last_edited.rb +1 -1
  285. data/mod/05_standard/set/rstar/rules.rb +3 -3
  286. data/mod/05_standard/set/rstar/rules_editor.rb +39 -39
  287. data/mod/05_standard/set/self/account_links.rb +21 -22
  288. data/mod/05_standard/set/self/admin_info.rb +5 -5
  289. data/mod/05_standard/set/self/alerts.rb +1 -1
  290. data/mod/05_standard/set/self/all.rb +1 -1
  291. data/mod/05_standard/set/self/foot.rb +1 -1
  292. data/mod/05_standard/set/self/head.rb +19 -22
  293. data/mod/05_standard/set/self/navbox.rb +3 -7
  294. data/mod/05_standard/set/self/now.rb +1 -1
  295. data/mod/05_standard/set/self/recent.rb +19 -25
  296. data/mod/05_standard/set/self/search.rb +2 -4
  297. data/mod/05_standard/set/self/signin.rb +6 -6
  298. data/mod/05_standard/set/self/stats.rb +31 -38
  299. data/mod/05_standard/set/self/version.rb +1 -2
  300. data/mod/05_standard/set/type/basic.rb +15 -17
  301. data/mod/05_standard/set/type/cardtype.rb +3 -3
  302. data/mod/05_standard/set/type/date.rb +1 -2
  303. data/mod/05_standard/set/type/file.rb +22 -33
  304. data/mod/05_standard/set/type/image.rb +30 -23
  305. data/mod/05_standard/set/type/layout_type.rb +4 -4
  306. data/mod/05_standard/set/type/list.rb +32 -38
  307. data/mod/05_standard/set/type/listed_by.rb +11 -13
  308. data/mod/05_standard/set/type/number.rb +5 -6
  309. data/mod/05_standard/set/type/phrase.rb +1 -1
  310. data/mod/05_standard/set/type/search_type.rb +25 -23
  311. data/mod/05_standard/set/type/session.rb +2 -3
  312. data/mod/05_standard/set/type/set.rb +46 -51
  313. data/mod/05_standard/set/type/signup.rb +18 -19
  314. data/mod/05_standard/set/type/toggle.rb +5 -5
  315. data/mod/05_standard/set/type/user.rb +6 -6
  316. data/mod/05_standard/spec/chunk/include_spec.rb +115 -98
  317. data/mod/05_standard/spec/chunk/link_spec.rb +58 -31
  318. data/mod/05_standard/spec/chunk/query_reference_spec.rb +12 -14
  319. data/mod/05_standard/spec/set/all/email_html_spec.rb +3 -3
  320. data/mod/05_standard/spec/set/all/error_spec.rb +3 -3
  321. data/mod/05_standard/spec/set/all/history_spec.rb +52 -38
  322. data/mod/05_standard/spec/set/all/links_spec.rb +2 -2
  323. data/mod/05_standard/spec/set/all/rich_html/editing_spec.rb +0 -1
  324. data/mod/05_standard/spec/set/all/rich_html/form_spec.rb +11 -11
  325. data/mod/05_standard/spec/set/all/rich_html/wrapper_spec.rb +4 -4
  326. data/mod/05_standard/spec/set/right/email_spec.rb +1 -4
  327. data/mod/05_standard/spec/set/right/password_spec.rb +4 -7
  328. data/mod/05_standard/spec/set/right/stats_spec.rb +2 -3
  329. data/mod/05_standard/spec/set/right/when_created_spec.rb +1 -1
  330. data/mod/05_standard/spec/set/right/when_last_edited_spec.rb +1 -1
  331. data/mod/05_standard/spec/set/rstar/rules_spec.rb +6 -6
  332. data/mod/05_standard/spec/set/self/all_spec.rb +11 -13
  333. data/mod/05_standard/spec/set/self/head_spec.rb +1 -3
  334. data/mod/05_standard/spec/set/self/navbox_spec.rb +1 -1
  335. data/mod/05_standard/spec/set/self/now_spec.rb +2 -2
  336. data/mod/05_standard/spec/set/self/signin_spec.rb +1 -1
  337. data/mod/05_standard/spec/set/self/stats_spec.rb +1 -1
  338. data/mod/05_standard/spec/set/self/version_spec.rb +2 -2
  339. data/mod/05_standard/spec/set/type/cardtype_spec.rb +3 -4
  340. data/mod/05_standard/spec/set/type/date_spec.rb +1 -1
  341. data/mod/05_standard/spec/set/type/email_template_spec.rb +5 -5
  342. data/mod/05_standard/spec/set/type/file_spec.rb +50 -28
  343. data/mod/05_standard/spec/set/type/html_spec.rb +12 -7
  344. data/mod/05_standard/spec/set/type/image_spec.rb +55 -45
  345. data/mod/05_standard/spec/set/type/layout_type_spec.rb +2 -2
  346. data/mod/05_standard/spec/set/type/listed_by_spec.rb +2 -2
  347. data/mod/05_standard/spec/set/type/number_spec.rb +1 -1
  348. data/mod/05_standard/spec/set/type/phrase_spec.rb +1 -1
  349. data/mod/05_standard/spec/set/type/search_type_spec.rb +15 -16
  350. data/mod/05_standard/spec/set/type/set_spec.rb +16 -17
  351. data/mod/05_standard/spec/set/type/signup_spec.rb +7 -5
  352. data/mod/05_standard/spec/set/type/toggle_spec.rb +4 -4
  353. data/mod/05_standard/spec/set/type/uri_spec.rb +11 -11
  354. data/mod/05_standard/spec/set/type/user_spec.rb +0 -1
  355. data/mod/06_bootstrap/set/all/bootstrap/form.rb +9 -10
  356. data/mod/06_bootstrap/set/all/bootstrap/helper.rb +22 -27
  357. data/mod/06_bootstrap/set/all/bootstrap/wrapper.rb +1 -2
  358. data/mod/06_bootstrap/set/all/rich_bootstrap.rb +1 -3
  359. data/mod/06_bootstrap/set/self/bootstrap_cards.rb +2 -2
  360. data/mod/06_bootstrap/set/self/bootstrap_js.rb +2 -2
  361. data/mod/06_bootstrap/set/self/bootswatch_shared.rb +19 -19
  362. data/mod/06_bootstrap/set/self/smartmenu_css.rb +2 -2
  363. data/mod/06_bootstrap/set/self/smartmenu_js.rb +3 -3
  364. data/mod/06_bootstrap/spec/set/all/bootstrap/form_spec.rb +5 -5
  365. data/spec/lib/card/action_spec.rb +4 -4
  366. data/spec/lib/card/cache_spec.rb +3 -5
  367. data/spec/lib/card/chunk_spec.rb +6 -8
  368. data/spec/lib/card/codename_spec.rb +4 -6
  369. data/spec/lib/card/content_spec.rb +12 -17
  370. data/spec/lib/card/diff_spec.rb +59 -61
  371. data/spec/lib/card/format_spec.rb +55 -34
  372. data/spec/lib/card/loader_spec.rb +35 -37
  373. data/spec/lib/card/name_spec.rb +159 -145
  374. data/spec/lib/card/query_spec.rb +4 -4
  375. data/spec/lib/card/reference_spec.rb +24 -24
  376. data/spec/lib/card/set_pattern_spec.rb +3 -3
  377. data/spec/lib/card/stage_director_spec.rb +218 -0
  378. data/spec/lib/card/subcards_spec.rb +12 -16
  379. data/spec/lib/card/success_spec.rb +16 -18
  380. data/spec/lib/card/view_cache_spec.rb +1 -1
  381. data/spec/mailers/mailer_spec.rb +3 -5
  382. data/spec/models/card/cardtype_spec.rb +40 -51
  383. data/spec/models/card/create_spec.rb +58 -39
  384. data/spec/models/card/trash_spec.rb +23 -32
  385. data/spec/models/card/type_transition_spec.rb +41 -32
  386. data/spec/models/card/validation_spec.rb +13 -15
  387. data/spec/models/card_spec.rb +48 -59
  388. data/spec/spec_helper.rb +26 -31
  389. metadata +16 -2
data/lib/card/stage.rb ADDED
@@ -0,0 +1,72 @@
1
+ class Card
2
+ # The process of writing a card change to the database is divided into
3
+ # 8 stages that are grouped in 3 phases.
4
+ #
5
+ # 'validation phase'
6
+ # * initialize stage
7
+ # * prepare_to_validate stage
8
+ # * validate stage
9
+ #
10
+ # 'storage phase'
11
+ # * prepare_to_store stage
12
+ # * store stage
13
+ # * finalize stage
14
+ #
15
+ # 'integration phase'
16
+ # * integrate stage
17
+ # * integrate_with_delay stage
18
+ #
19
+ #
20
+ module Stage
21
+ STAGES = [:initialize, :prepare_to_validate, :validate, :prepare_to_store,
22
+ :store, :finalize, :integrate, :integrate_with_delay].freeze
23
+ STAGE_INDEX = {}
24
+ STAGES.each_with_index do |stage, i|
25
+ STAGE_INDEX[stage] = i
26
+ end
27
+ STAGE_INDEX.freeze
28
+
29
+ def stage_symbol index
30
+ case index
31
+ when Symbol
32
+ return index if STAGE_INDEX[index]
33
+ when Integer
34
+ return STAGES[index] if index < STAGES.size
35
+ end
36
+ raise Card::Error, "not a valid stage index: #{index}"
37
+ end
38
+
39
+ def stage_index stage
40
+ case stage
41
+ when Symbol then
42
+ return STAGE_INDEX[stage]
43
+ when Integer then
44
+ return stage
45
+ else
46
+ raise Card::Error, "not a valid stage: #{stage}"
47
+ end
48
+ end
49
+
50
+ def stage_ok? opts
51
+ stage && (
52
+ (opts[:during] && in?(opts[:during])) ||
53
+ (opts[:before] && before?(opts[:before])) ||
54
+ (opts[:after] && after?(opts[:after])) ||
55
+ true # no phase restriction in opts
56
+ )
57
+ end
58
+
59
+ def before? allowed_phase
60
+ STAGE_INDEX[allowed_phase] > STAGE_INDEX[stage]
61
+ end
62
+
63
+ def after? allowed_phase
64
+ STAGE_INDEX[allowed_phase] < STAGE_INDEX[stage]
65
+ end
66
+
67
+ def in? allowed_phase
68
+ (allowed_phase.is_a?(Array) && allowed_phase.include?(stage)) ||
69
+ allowed_phase == stage
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,231 @@
1
+
2
+ class Card
3
+ # A 'StageDirector' executes the stages of a card when the card gets created,
4
+ # updated or deleted.
5
+ # For subcards, i.e. other cards that are changed in the same act, a
6
+ # StageDirector has StageSubdirectors that take care of the stages for
7
+ # those cards
8
+ #
9
+ # In general a stage is executed for all involved cards before the
10
+ # StageDirector proceeds with the next stage.
11
+ # Only exception is the finalize stage.
12
+ # The finalize stage of a subcard is executed immediately after its store
13
+ # stage. When all subcards are finalized the supercard's finalize stage is
14
+ # executed.
15
+ #
16
+ # If a subcard is added in a stage then it catches up at the end of the stage
17
+ # to the current stage.
18
+ # For example if you add a subcard in a card's :prepare_to_store stage then
19
+ # after that stage the stages :initialize, :prepare_to_validate,
20
+ # :validate and :prepare_to_store are executed for the subcard.
21
+ #
22
+ # Stages are executed with pre-order depth-first search.
23
+ # That means if A has subcards AA and AB; AAA is subcard of AA and ABA
24
+ # subcard of AB then the order of execution is
25
+ # A -> AA -> AAA -> AB -> ABA
26
+ #
27
+ # A special case can happen in the store phase.
28
+ # If the id of a subcard is needed for a supercard
29
+ # (for example as left_id or as type_id) and the subcard doesn't
30
+ # have an id yet (because it gets created in the same act)
31
+ # then the subcard's store stage is executed before the supercard's store
32
+ # stage
33
+ class StageDirector
34
+ include Stage
35
+
36
+ attr_accessor :prior_store, :act, :card, :stage, :parent, :main,
37
+ :subdirectors
38
+ attr_reader :running
39
+ alias running? running
40
+ alias main? main
41
+
42
+ def initialize card, opts={}, main=true
43
+ @card = card
44
+ @card.director = self
45
+ @card.prepare_for_phases
46
+ @stage = nil
47
+ @running = false
48
+ @parent = opts[:parent]
49
+ # has card to be stored before the supercard?
50
+ @prior_store = opts[:priority]
51
+ @main = main
52
+ @subdirectors = SubdirectorArray.initialize_with_subcards(self)
53
+ register
54
+ end
55
+
56
+ def register
57
+ Card::DirectorRegister.add self
58
+ end
59
+
60
+ def unregister
61
+ @card.director = nil
62
+ @subdirectors = nil
63
+ @stage = nil
64
+ @action = nil
65
+ Card::DirectorRegister.delete self
66
+ end
67
+
68
+ def validation_phase
69
+ @running = true
70
+ run_single_stage :initialize
71
+ run_single_stage :prepare_to_validate
72
+ run_single_stage :validate
73
+ @card.expire_pieces if @card.errors.any?
74
+ @card.errors.empty?
75
+ end
76
+
77
+ # everything in here can use dirty marks
78
+ def storage_phase &block
79
+ # for a subcard :prepare_to_store was already executed
80
+ # don't execute it twice
81
+ catch_up_to_stage :prepare_to_store
82
+ run_single_stage :store, &block
83
+ run_single_stage :finalize
84
+ ensure
85
+ @from_trash = nil
86
+ end
87
+
88
+ # dirty marks are gone in this phase
89
+ def integration_phase
90
+ run_single_stage :integrate
91
+ run_single_stage :integrate_with_delay
92
+ rescue => e # don't rollback
93
+ Card::Error.current = e
94
+ @card.notable_exception_raised
95
+ return false
96
+ end
97
+
98
+ def catch_up_to_stage next_stage
99
+ @stage ||= -1
100
+ (@stage + 1).upto(stage_index(next_stage)) do |i|
101
+ run_single_stage stage_symbol(i)
102
+ end
103
+ end
104
+
105
+ def call_after_store &block
106
+ @call_after_store ||= []
107
+ @call_after_store << block
108
+ end
109
+
110
+ def need_act
111
+ act_director = main_director
112
+ unless act_director
113
+ raise Card::Error, 'act requested without a main stage director'
114
+ end
115
+ act_director.act ||= Card::Act.create(ip_address: Env.ip)
116
+ @card.current_act = @act = act_director.act
117
+ end
118
+
119
+ def main_director
120
+ if main?
121
+ self
122
+ else
123
+ DirectorRegister.act_director || (@parent && @parent.main_director)
124
+ end
125
+ end
126
+
127
+ private
128
+
129
+ def run_single_stage stage, &block
130
+ # puts "#{@card.name}: #{stage} stage".red
131
+ @stage = stage_index stage
132
+ return if @card.errors.any? && @stage <= stage_index(:validate)
133
+
134
+ # in the store stage it can be necessary that
135
+ # other subcards must be saved before we save this card
136
+ if stage == :store
137
+ store(&block)
138
+ else
139
+ run_stage_callbacks stage
140
+ run_subdirector_stages stage unless stage == :finalize
141
+ end
142
+ rescue => e
143
+ @card.rescue_event e
144
+ end
145
+
146
+ def run_stage_callbacks stage
147
+ # we use abort :success in the :store stage for :save_draft
148
+ if stage_index(stage) <= stage_index(:store) && !main?
149
+ @card.abortable do
150
+ @card.run_callbacks :"#{stage}_stage"
151
+ end
152
+ else
153
+ @card.run_callbacks :"#{stage}_stage"
154
+ end
155
+ end
156
+
157
+ def run_subdirector_stages stage
158
+ @subdirectors.each do |subdir|
159
+ subdir.catch_up_to_stage stage
160
+ end
161
+ ensure
162
+ @card.handle_subcard_errors
163
+ end
164
+
165
+ # handle the store stage
166
+ # The tricky part here is to preserve the dirty marks on the subcards'
167
+ # attributes for the finalize stage.
168
+ # To achieve this we can't just call the :store and :finlaize callbacks on
169
+ # the subcards as we do in the other phases.
170
+ # Instead we have to call `save` on the subcards
171
+ # and use the ActiveRecord :around_save callback to run the :store and
172
+ # :finalize stages
173
+ def store &save_block
174
+ if main? && !block_given?
175
+ raise Card::Error, 'need block to store main card'
176
+ end
177
+ # the block is the ActiveRecord block from the around save callback that
178
+ # saves the card
179
+ if block_given?
180
+ run_stage_callbacks :store
181
+ store_with_subcards(&save_block)
182
+ else
183
+ store_and_finalize_as_subcard
184
+ end
185
+ end
186
+
187
+ def store_with_subcards
188
+ store_prior_subcards
189
+ yield
190
+ if @call_after_store
191
+ @call_after_store.each do |handle_id|
192
+ handle_id.call(@card.id)
193
+ end
194
+ end
195
+ store_subcards
196
+ @virtual = false # TODO: find a better place for this
197
+ ensure
198
+ @card.handle_subcard_errors
199
+ end
200
+
201
+ # store subcards whose ids we need for this card
202
+ def store_prior_subcards
203
+ @subdirectors.each do |subdir|
204
+ next unless subdir.prior_store
205
+ subdir.catch_up_to_stage :store
206
+ end
207
+ end
208
+
209
+ def store_subcards
210
+ @subdirectors.each do |subdir|
211
+ next if subdir.prior_store
212
+ subdir.catch_up_to_stage :store
213
+ end
214
+ end
215
+
216
+ # trigger the storage_phase, skip the other phases
217
+ # At this point the :prepare_to_store stage was already executed
218
+ # by the parent director. So the storage phase will only run
219
+ # the :store stage and the :finalize stage
220
+ def store_and_finalize_as_subcard
221
+ @card.skip_phases = true
222
+ @card.save! validate: false
223
+ end
224
+ end
225
+
226
+ class StageSubdirector < StageDirector
227
+ def initialize card, opts={}
228
+ super card, opts, false
229
+ end
230
+ end
231
+ end
data/lib/card/subcards.rb CHANGED
@@ -11,29 +11,13 @@
11
11
  class Card
12
12
  def subcards
13
13
  @subcards ||= Subcards.new(self)
14
- end
15
-
16
- def preserve_subcards
17
- return unless subcards.present?
18
- Card.cache.soft.write subcards_cache_key, @subcards
19
- end
20
-
21
- def restore_subcards
22
- cached_subcards = Card.cache.soft.read(subcards_cache_key)
23
- return unless cached_subcards
24
- @subcards = cached_subcards
25
- @subcards.context_card = self
14
+ # @subcards ||= (director && director.subcards)
26
15
  end
27
16
 
28
17
  def expire_subcards
29
- Card.cache.soft.delete subcards_cache_key
30
18
  subcards.clear
31
19
  end
32
20
 
33
- def subcards_cache_key
34
- "#{key}#SUBCARDS#"
35
- end
36
-
37
21
  class Subcards
38
22
  attr_accessor :context_card, :keys
39
23
  def initialize context_card
@@ -48,6 +32,15 @@ class Card
48
32
  @keys = ::Set.new
49
33
  end
50
34
 
35
+ def deep_clear cleared=::Set.new
36
+ each_card do |card|
37
+ next if cleared.include? card.id
38
+ cleared << card.id
39
+ card.subcards.deep_clear cleared
40
+ end
41
+ clear
42
+ end
43
+
51
44
  def remove name_or_card
52
45
  key = case name_or_card
53
46
  when Card
@@ -96,8 +89,15 @@ class Card
96
89
  end
97
90
  end
98
91
 
99
- def rename old_name, new_name
92
+ def catch_up_to_stage stage_index
93
+ each_card do |subcard|
94
+ subcard.catch_up_to_stage stage_index
95
+ end
96
+ end
97
+
98
+ def rename old_name, _new_name
100
99
  return unless @keys.include? old_name.to_name.key
100
+ # FIXME: something should happen here
101
101
  end
102
102
 
103
103
  def << value
@@ -122,7 +122,7 @@ class Card
122
122
  end
123
123
  end
124
124
 
125
- alias_method :each, :each_card
125
+ alias each each_card
126
126
 
127
127
  def each_with_key
128
128
  @keys.each do |key|
@@ -146,9 +146,7 @@ class Card
146
146
 
147
147
  def field name
148
148
  key = field_name_to_key name
149
- if @keys.include? key
150
- fetch_subcard key
151
- end
149
+ fetch_subcard key if @keys.include? key
152
150
  end
153
151
 
154
152
  def card name
@@ -173,8 +171,8 @@ class Card
173
171
  end
174
172
  end
175
173
 
176
- alias_method :add_field, :add_child
177
- alias_method :remove_field, :remove_child
174
+ alias add_field add_child
175
+ alias remove_field remove_child
178
176
 
179
177
  def present?
180
178
  @keys.present?
@@ -240,7 +238,41 @@ class Card
240
238
  end
241
239
  @keys << card.key
242
240
  Card.write_to_soft_cache card
241
+ card.director = @context_card.director.subdirectors.add(card)
243
242
  card
244
243
  end
245
244
  end
245
+
246
+ def right_id= card_or_id
247
+ write_card_or_id :right_id, card_or_id
248
+ end
249
+
250
+ def left_id= card_or_id
251
+ write_card_or_id :left_id, card_or_id
252
+ end
253
+
254
+ def type_id= card_or_id
255
+ write_card_or_id :type_id, card_or_id
256
+ end
257
+
258
+ def write_card_or_id attribute, card_or_id
259
+ if card_or_id.is_a? Card
260
+ card = card_or_id
261
+ if card.id
262
+ write_attribute attribute, card.id
263
+ else
264
+ add_subcard card
265
+ card.director.prior_store = true
266
+ with_id_when_exists(card) do |id|
267
+ write_attribute attribute, id
268
+ end
269
+ end
270
+ else
271
+ write_attribute attribute, card_or_id
272
+ end
273
+ end
274
+
275
+ def with_id_when_exists card, &block
276
+ card.director.call_after_store(&block)
277
+ end
246
278
  end
@@ -0,0 +1,31 @@
1
+ class Card
2
+ class SubdirectorArray < Array
3
+ def self.initialize_with_subcards parent
4
+ dir_array = new(parent)
5
+ parent.card.subcards.each_card do |subcard|
6
+ dir_array.add subcard
7
+ end
8
+ dir_array
9
+ end
10
+
11
+ def initialize parent
12
+ @parent = parent
13
+ super()
14
+ end
15
+
16
+ def add card
17
+ each do |dir|
18
+ return dir if dir.card == card
19
+ end
20
+ dir = Card::DirectorRegister.fetch card, parent: @parent
21
+ dir.main = false
22
+ dir.parent = @parent
23
+ self << dir
24
+ dir
25
+ end
26
+
27
+ def delete card
28
+ delete_if { |dir| dir.card == card }
29
+ end
30
+ end
31
+ end