alchemy_cms 4.4.4 → 5.0.0.beta2

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 (386) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +56 -18
  3. data/.github/workflows/stale.yml +1 -1
  4. data/.gitignore +20 -2
  5. data/.hound.yml +2 -1
  6. data/.prettierrc +6 -0
  7. data/.rubocop.yml +33 -20
  8. data/CHANGELOG.md +121 -0
  9. data/Gemfile +24 -22
  10. data/README.md +31 -19
  11. data/Rakefile +10 -8
  12. data/alchemy_cms.gemspec +7 -5
  13. data/app/assets/javascripts/alchemy/admin.js +1 -2
  14. data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +2 -1
  15. data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +0 -2
  16. data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +5 -5
  17. data/app/assets/javascripts/alchemy/alchemy.page_sorter.js +17 -17
  18. data/app/assets/javascripts/alchemy/node_select.js +39 -0
  19. data/app/assets/javascripts/alchemy/templates/index.js +2 -0
  20. data/app/assets/javascripts/alchemy/templates/node.hbs +16 -0
  21. data/app/assets/javascripts/alchemy/templates/node_folder.hbs +3 -0
  22. data/app/assets/javascripts/alchemy/templates/page.hbs +1 -1
  23. data/app/assets/stylesheets/alchemy/_mixins.scss +2 -3
  24. data/app/assets/stylesheets/alchemy/_variables.scss +2 -2
  25. data/app/assets/stylesheets/alchemy/admin.scss +3 -2
  26. data/app/assets/stylesheets/alchemy/base.scss +0 -1
  27. data/app/assets/stylesheets/alchemy/elements.scss +1 -1
  28. data/app/assets/stylesheets/alchemy/forms.scss +5 -0
  29. data/app/assets/stylesheets/alchemy/lists.scss +0 -8
  30. data/app/assets/stylesheets/alchemy/node-select.scss +43 -0
  31. data/app/assets/stylesheets/alchemy/nodes.scss +6 -1
  32. data/app/assets/stylesheets/alchemy/sitemap.scss +63 -21
  33. data/app/assets/stylesheets/alchemy/tables.scss +1 -24
  34. data/app/controllers/alchemy/admin/attachments_controller.rb +8 -7
  35. data/app/controllers/alchemy/admin/base_controller.rb +13 -33
  36. data/app/controllers/alchemy/admin/clipboard_controller.rb +5 -4
  37. data/app/controllers/alchemy/admin/contents_controller.rb +1 -2
  38. data/app/controllers/alchemy/admin/dashboard_controller.rb +10 -9
  39. data/app/controllers/alchemy/admin/elements_controller.rb +20 -20
  40. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +12 -14
  41. data/app/controllers/alchemy/admin/languages_controller.rb +35 -2
  42. data/app/controllers/alchemy/admin/layoutpages_controller.rb +5 -2
  43. data/app/controllers/alchemy/admin/nodes_controller.rb +5 -14
  44. data/app/controllers/alchemy/admin/pages_controller.rb +50 -63
  45. data/app/controllers/alchemy/admin/pictures_controller.rb +16 -16
  46. data/app/controllers/alchemy/admin/resources_controller.rb +21 -13
  47. data/app/controllers/alchemy/admin/sites_controller.rb +18 -0
  48. data/app/controllers/alchemy/admin/styleguide_controller.rb +1 -0
  49. data/app/controllers/alchemy/admin/tags_controller.rb +5 -3
  50. data/app/controllers/alchemy/admin/trash_controller.rb +6 -6
  51. data/app/controllers/alchemy/api/base_controller.rb +2 -2
  52. data/app/controllers/alchemy/api/contents_controller.rb +4 -4
  53. data/app/controllers/alchemy/api/elements_controller.rb +8 -8
  54. data/app/controllers/alchemy/api/nodes_controller.rb +65 -0
  55. data/app/controllers/alchemy/api/pages_controller.rb +15 -22
  56. data/app/controllers/alchemy/attachments_controller.rb +5 -5
  57. data/app/controllers/alchemy/base_controller.rb +10 -9
  58. data/app/controllers/alchemy/messages_controller.rb +16 -23
  59. data/app/controllers/alchemy/pages_controller.rb +13 -11
  60. data/app/controllers/concerns/alchemy/admin/archive_overlay.rb +3 -2
  61. data/app/controllers/concerns/alchemy/admin/current_language.rb +23 -0
  62. data/app/controllers/concerns/alchemy/admin/uploader_responses.rb +5 -5
  63. data/app/controllers/concerns/alchemy/legacy_page_redirects.rb +4 -4
  64. data/app/controllers/concerns/alchemy/page_redirects.rb +2 -9
  65. data/app/controllers/concerns/alchemy/site_redirects.rb +2 -2
  66. data/app/decorators/alchemy/content_editor.rb +55 -0
  67. data/app/decorators/alchemy/element_editor.rb +39 -0
  68. data/app/helpers/alchemy/admin/attachments_helper.rb +6 -6
  69. data/app/helpers/alchemy/admin/base_helper.rb +36 -35
  70. data/app/helpers/alchemy/admin/contents_helper.rb +3 -3
  71. data/app/helpers/alchemy/admin/elements_helper.rb +3 -88
  72. data/app/helpers/alchemy/admin/essences_helper.rb +8 -117
  73. data/app/helpers/alchemy/admin/form_helper.rb +1 -1
  74. data/app/helpers/alchemy/admin/navigation_helper.rb +24 -23
  75. data/app/helpers/alchemy/admin/pages_helper.rb +12 -12
  76. data/app/helpers/alchemy/admin/pictures_helper.rb +4 -6
  77. data/app/helpers/alchemy/admin/tags_helper.rb +8 -7
  78. data/app/helpers/alchemy/base_helper.rb +13 -8
  79. data/app/helpers/alchemy/elements_block_helper.rb +2 -31
  80. data/app/helpers/alchemy/elements_helper.rb +12 -58
  81. data/app/helpers/alchemy/pages_helper.rb +24 -174
  82. data/app/helpers/alchemy/url_helper.rb +2 -1
  83. data/app/mailers/alchemy/base_mailer.rb +1 -1
  84. data/app/mailers/alchemy/messages_mailer.rb +1 -1
  85. data/app/models/alchemy/attachment.rb +20 -18
  86. data/app/models/alchemy/base_record.rb +2 -5
  87. data/app/models/alchemy/content.rb +33 -52
  88. data/app/models/alchemy/content/factory.rb +24 -31
  89. data/app/models/alchemy/element.rb +45 -53
  90. data/app/models/alchemy/element/definitions.rb +4 -4
  91. data/app/models/alchemy/element/element_contents.rb +9 -6
  92. data/app/models/alchemy/element/element_essences.rb +4 -3
  93. data/app/models/alchemy/element/presenters.rb +3 -2
  94. data/app/models/alchemy/element_to_page.rb +1 -1
  95. data/app/models/alchemy/essence_boolean.rb +1 -3
  96. data/app/models/alchemy/essence_date.rb +2 -3
  97. data/app/models/alchemy/essence_file.rb +4 -4
  98. data/app/models/alchemy/essence_html.rb +1 -3
  99. data/app/models/alchemy/essence_link.rb +1 -3
  100. data/app/models/alchemy/essence_node.rb +18 -0
  101. data/app/models/alchemy/essence_page.rb +3 -16
  102. data/app/models/alchemy/essence_picture.rb +17 -16
  103. data/app/models/alchemy/essence_picture_view.rb +7 -6
  104. data/app/models/alchemy/essence_richtext.rb +1 -3
  105. data/app/models/alchemy/essence_select.rb +1 -3
  106. data/app/models/alchemy/essence_text.rb +0 -2
  107. data/app/models/alchemy/folded_page.rb +1 -0
  108. data/app/models/alchemy/language.rb +21 -35
  109. data/app/models/alchemy/language/code.rb +4 -4
  110. data/app/models/alchemy/legacy_page_url.rb +1 -1
  111. data/app/models/alchemy/message.rb +3 -3
  112. data/app/models/alchemy/node.rb +55 -9
  113. data/app/models/alchemy/page.rb +53 -123
  114. data/app/models/alchemy/page/fixed_attributes.rb +3 -2
  115. data/app/models/alchemy/page/page_elements.rb +35 -44
  116. data/app/models/alchemy/page/page_naming.rb +20 -70
  117. data/app/models/alchemy/page/page_natures.rb +7 -34
  118. data/app/models/alchemy/page/page_scopes.rb +23 -29
  119. data/app/models/alchemy/page/url_path.rb +64 -0
  120. data/app/models/alchemy/picture.rb +40 -30
  121. data/app/models/alchemy/picture/preprocessor.rb +26 -0
  122. data/app/models/alchemy/picture/transformations.rb +9 -7
  123. data/app/models/alchemy/picture/url.rb +5 -5
  124. data/app/models/alchemy/site.rb +6 -36
  125. data/app/models/alchemy/site/layout.rb +2 -2
  126. data/app/models/concerns/alchemy/touch_elements.rb +24 -0
  127. data/app/serializers/alchemy/content_serializer.rb +0 -3
  128. data/app/serializers/alchemy/essence_boolean_serializer.rb +3 -3
  129. data/app/serializers/alchemy/essence_date_serializer.rb +3 -3
  130. data/app/serializers/alchemy/essence_file_serializer.rb +4 -2
  131. data/app/serializers/alchemy/essence_html_serializer.rb +3 -3
  132. data/app/serializers/alchemy/essence_link_serializer.rb +3 -3
  133. data/app/serializers/alchemy/essence_picture_serializer.rb +5 -4
  134. data/app/serializers/alchemy/essence_richtext_serializer.rb +3 -3
  135. data/app/serializers/alchemy/essence_select_serializer.rb +3 -3
  136. data/app/serializers/alchemy/essence_text_serializer.rb +5 -4
  137. data/app/serializers/alchemy/node_serializer.rb +14 -0
  138. data/app/serializers/alchemy/page_serializer.rb +2 -1
  139. data/app/serializers/alchemy/page_tree_serializer.rb +11 -14
  140. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +1 -2
  141. data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +1 -2
  142. data/app/views/alchemy/admin/attachments/_files_list.html.erb +4 -4
  143. data/app/views/alchemy/admin/contents/create.js.erb +1 -3
  144. data/app/views/alchemy/admin/elements/_element.html.erb +9 -18
  145. data/app/views/alchemy/admin/elements/create.js.erb +1 -1
  146. data/app/views/alchemy/admin/elements/fold.js.erb +1 -1
  147. data/app/views/alchemy/admin/elements/index.html.erb +3 -3
  148. data/app/views/alchemy/admin/essence_files/assign.js.erb +1 -6
  149. data/app/views/alchemy/admin/essence_files/edit.html.erb +1 -1
  150. data/app/views/alchemy/admin/essence_pictures/assign.js.erb +1 -7
  151. data/app/views/alchemy/admin/essence_pictures/crop.html.erb +1 -1
  152. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +7 -7
  153. data/app/views/alchemy/admin/essence_pictures/update.js.erb +1 -1
  154. data/app/views/alchemy/admin/languages/_form.html.erb +5 -5
  155. data/app/views/alchemy/admin/languages/_table.html.erb +3 -3
  156. data/app/views/alchemy/admin/languages/edit.html.erb +1 -0
  157. data/app/views/alchemy/admin/languages/index.html.erb +23 -4
  158. data/app/views/alchemy/admin/languages/new.html.erb +1 -0
  159. data/app/views/alchemy/admin/layoutpages/index.html.erb +6 -2
  160. data/app/views/alchemy/admin/nodes/_form.html.erb +23 -15
  161. data/app/views/alchemy/admin/nodes/_node.html.erb +5 -19
  162. data/app/views/alchemy/admin/nodes/index.html.erb +3 -18
  163. data/app/views/alchemy/admin/pages/_create_language_form.html.erb +0 -8
  164. data/app/views/alchemy/admin/pages/_form.html.erb +1 -2
  165. data/app/views/alchemy/admin/pages/_new_page_form.html.erb +1 -0
  166. data/app/views/alchemy/admin/pages/_page.html.erb +14 -25
  167. data/app/views/alchemy/admin/pages/_page_infos.html.erb +0 -4
  168. data/app/views/alchemy/admin/pages/_sitemap.html.erb +6 -0
  169. data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
  170. data/app/views/alchemy/admin/pages/info.html.erb +0 -9
  171. data/app/views/alchemy/admin/pages/unlock.js.erb +13 -6
  172. data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +0 -2
  173. data/app/views/alchemy/admin/partials/_routes.html.erb +8 -0
  174. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +1 -5
  175. data/app/views/alchemy/admin/pictures/_overlay_picture_list.html.erb +1 -1
  176. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +1 -2
  177. data/app/views/alchemy/admin/pictures/index.html.erb +18 -3
  178. data/app/views/alchemy/admin/resources/_resource.html.erb +1 -1
  179. data/app/views/alchemy/admin/resources/_table.html.erb +2 -2
  180. data/app/views/alchemy/admin/sites/_form.html.erb +8 -0
  181. data/app/views/alchemy/admin/sites/edit.html.erb +1 -0
  182. data/app/views/alchemy/admin/sites/index.html.erb +21 -9
  183. data/app/views/alchemy/admin/sites/new.html.erb +1 -0
  184. data/app/views/alchemy/admin/tags/index.html.erb +2 -2
  185. data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +10 -12
  186. data/app/views/alchemy/essences/_essence_date_editor.html.erb +11 -8
  187. data/app/views/alchemy/essences/_essence_file_editor.html.erb +16 -17
  188. data/app/views/alchemy/essences/_essence_html_editor.html.erb +8 -5
  189. data/app/views/alchemy/essences/_essence_link_editor.html.erb +18 -15
  190. data/app/views/alchemy/essences/_essence_node_editor.html.erb +27 -0
  191. data/app/views/alchemy/essences/_essence_node_view.html.erb +1 -0
  192. data/app/views/alchemy/essences/_essence_page_editor.html.erb +14 -11
  193. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +22 -20
  194. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +10 -7
  195. data/app/views/alchemy/essences/_essence_select_editor.html.erb +12 -16
  196. data/app/views/alchemy/essences/_essence_text_editor.html.erb +18 -17
  197. data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +6 -11
  198. data/app/views/alchemy/pages/show.rss.builder +3 -2
  199. data/app/views/layouts/alchemy/admin.html.erb +1 -0
  200. data/babel.config.js +12 -0
  201. data/bin/rails +5 -4
  202. data/config/alchemy/config.yml +23 -22
  203. data/config/brakeman.ignore +1 -1
  204. data/config/initializers/assets.rb +2 -1
  205. data/config/initializers/dragonfly.rb +2 -1
  206. data/config/initializers/mime_types.rb +1 -0
  207. data/config/initializers/mini_profiler.rb +3 -2
  208. data/config/initializers/simple_form.rb +6 -6
  209. data/config/locales/alchemy.en.yml +37 -14
  210. data/config/routes.rb +32 -28
  211. data/config/spring.rb +3 -2
  212. data/db/migrate/20200226213334_alchemy_four_point_four.rb +313 -0
  213. data/db/migrate/20200423073425_create_alchemy_essence_nodes.rb +11 -0
  214. data/db/migrate/20200504210159_remove_site_id_from_nodes.rb +28 -0
  215. data/db/migrate/20200505215518_add_language_id_foreign_key_to_alchemy_pages.rb +8 -0
  216. data/db/migrate/20200511113603_add_menu_type_to_alchemy_nodes.rb +27 -0
  217. data/db/migrate/20200514091507_make_page_layoutpage_null_false.rb +6 -0
  218. data/db/migrate/20200519073500_remove_visible_from_alchemy_pages.rb +24 -0
  219. data/lib/alchemy/admin/locale.rb +3 -1
  220. data/lib/alchemy/admin/preview_url.rb +85 -0
  221. data/lib/alchemy/auth_accessors.rb +8 -7
  222. data/lib/alchemy/cache_digests/template_tracker.rb +5 -4
  223. data/lib/alchemy/config.rb +26 -2
  224. data/lib/alchemy/configuration_methods.rb +3 -1
  225. data/lib/alchemy/controller_actions.rb +6 -5
  226. data/lib/alchemy/deprecation.rb +2 -1
  227. data/lib/alchemy/elements_finder.rb +5 -5
  228. data/lib/alchemy/engine.rb +23 -8
  229. data/lib/alchemy/errors.rb +0 -7
  230. data/lib/alchemy/essence.rb +17 -16
  231. data/lib/alchemy/filetypes.rb +5 -5
  232. data/lib/alchemy/forms/builder.rb +4 -4
  233. data/lib/alchemy/hints.rb +1 -1
  234. data/lib/alchemy/i18n.rb +2 -1
  235. data/lib/alchemy/modules.rb +12 -12
  236. data/lib/alchemy/name_conversions.rb +5 -5
  237. data/lib/alchemy/on_page_layout/callbacks_runner.rb +1 -0
  238. data/lib/alchemy/page_layout.rb +15 -12
  239. data/lib/alchemy/paths.rb +1 -1
  240. data/lib/alchemy/permissions.rb +7 -6
  241. data/lib/alchemy/resource.rb +23 -13
  242. data/lib/alchemy/resources_helper.rb +12 -18
  243. data/lib/alchemy/routing_constraints.rb +1 -1
  244. data/lib/alchemy/seeder.rb +42 -14
  245. data/lib/alchemy/shell.rb +13 -10
  246. data/lib/alchemy/taggable.rb +1 -0
  247. data/lib/alchemy/tasks/tidy.rb +4 -3
  248. data/lib/alchemy/test_support/config_stubbing.rb +1 -0
  249. data/lib/alchemy/test_support/essence_shared_examples.rb +72 -72
  250. data/lib/alchemy/test_support/factories.rb +1 -1
  251. data/lib/alchemy/test_support/factories/attachment_factory.rb +5 -5
  252. data/lib/alchemy/test_support/factories/content_factory.rb +6 -6
  253. data/lib/alchemy/test_support/factories/dummy_user_factory.rb +7 -7
  254. data/lib/alchemy/test_support/factories/element_factory.rb +9 -9
  255. data/lib/alchemy/test_support/factories/essence_file_factory.rb +3 -3
  256. data/lib/alchemy/test_support/factories/essence_page_factory.rb +3 -3
  257. data/lib/alchemy/test_support/factories/essence_picture_factory.rb +4 -4
  258. data/lib/alchemy/test_support/factories/essence_text_factory.rb +3 -3
  259. data/lib/alchemy/test_support/factories/language_factory.rb +21 -14
  260. data/lib/alchemy/test_support/factories/node_factory.rb +8 -8
  261. data/lib/alchemy/test_support/factories/page_factory.rb +15 -27
  262. data/lib/alchemy/test_support/factories/picture_factory.rb +5 -5
  263. data/lib/alchemy/test_support/factories/site_factory.rb +7 -6
  264. data/lib/alchemy/test_support/integration_helpers.rb +1 -0
  265. data/lib/alchemy/test_support/shared_contexts.rb +5 -4
  266. data/lib/alchemy/test_support/shared_uploader_examples.rb +4 -3
  267. data/lib/alchemy/tinymce.rb +15 -13
  268. data/lib/alchemy/upgrader.rb +8 -7
  269. data/lib/alchemy/upgrader/five_point_zero.rb +41 -0
  270. data/lib/alchemy/upgrader/tasks/element_views_updater.rb +4 -4
  271. data/lib/alchemy/upgrader/tasks/harden_gutentag_migrations.rb +29 -0
  272. data/lib/alchemy/version.rb +1 -1
  273. data/lib/alchemy_cms.rb +52 -50
  274. data/lib/{rails/generators → generators}/alchemy/base.rb +5 -4
  275. data/lib/{rails/generators → generators}/alchemy/elements/elements_generator.rb +13 -9
  276. data/lib/{rails/generators → generators}/alchemy/elements/templates/view.html.erb +0 -0
  277. data/lib/{rails/generators → generators}/alchemy/elements/templates/view.html.haml +0 -0
  278. data/lib/{rails/generators → generators}/alchemy/elements/templates/view.html.slim +0 -0
  279. data/lib/{rails/generators → generators}/alchemy/essence/essence_generator.rb +15 -13
  280. data/lib/generators/alchemy/essence/templates/editor.html.erb +17 -0
  281. data/lib/{rails/generators → generators}/alchemy/essence/templates/view.html.erb +0 -0
  282. data/lib/{rails/generators → generators}/alchemy/install/files/_article.html.erb +0 -0
  283. data/lib/{rails/generators → generators}/alchemy/install/files/_standard.html.erb +0 -0
  284. data/lib/{rails/generators → generators}/alchemy/install/files/alchemy.en.yml +0 -0
  285. data/lib/generators/alchemy/install/files/alchemy_admin.js +1 -0
  286. data/lib/{rails/generators → generators}/alchemy/install/files/all.css +0 -0
  287. data/lib/{rails/generators → generators}/alchemy/install/files/all.js +0 -0
  288. data/lib/{rails/generators → generators}/alchemy/install/files/application.html.erb +0 -0
  289. data/lib/{rails/generators → generators}/alchemy/install/files/article.scss +0 -0
  290. data/lib/generators/alchemy/install/install_generator.rb +110 -0
  291. data/lib/{rails/generators → generators}/alchemy/install/templates/dragonfly.rb.tt +0 -0
  292. data/lib/{rails/generators → generators}/alchemy/install/templates/elements.yml.tt +0 -0
  293. data/lib/generators/alchemy/install/templates/menus.yml.tt +8 -0
  294. data/lib/{rails/generators → generators}/alchemy/install/templates/page_layouts.yml.tt +0 -0
  295. data/lib/{rails/generators → generators}/alchemy/menus/menus_generator.rb +5 -5
  296. data/lib/{rails/generators → generators}/alchemy/menus/templates/node.html.erb +1 -4
  297. data/lib/{rails/generators → generators}/alchemy/menus/templates/node.html.haml +1 -4
  298. data/lib/{rails/generators → generators}/alchemy/menus/templates/node.html.slim +1 -4
  299. data/lib/{rails/generators → generators}/alchemy/menus/templates/wrapper.html.erb +1 -1
  300. data/lib/{rails/generators → generators}/alchemy/menus/templates/wrapper.html.haml +2 -2
  301. data/lib/{rails/generators → generators}/alchemy/menus/templates/wrapper.html.slim +2 -2
  302. data/lib/{rails/generators → generators}/alchemy/module/module_generator.rb +3 -2
  303. data/lib/{rails/generators → generators}/alchemy/module/templates/ability.rb.tt +0 -0
  304. data/lib/{rails/generators → generators}/alchemy/module/templates/controller.rb.tt +0 -0
  305. data/lib/{rails/generators → generators}/alchemy/module/templates/module_config.rb.tt +0 -0
  306. data/lib/{rails/generators → generators}/alchemy/page_layouts/page_layouts_generator.rb +5 -4
  307. data/lib/{rails/generators → generators}/alchemy/page_layouts/templates/layout.html.erb +0 -0
  308. data/lib/{rails/generators → generators}/alchemy/page_layouts/templates/layout.html.haml +0 -0
  309. data/lib/{rails/generators → generators}/alchemy/page_layouts/templates/layout.html.slim +0 -0
  310. data/lib/{rails/generators → generators}/alchemy/site_layouts/site_layouts_generator.rb +4 -2
  311. data/lib/{rails/generators → generators}/alchemy/site_layouts/templates/layout.html.erb +0 -0
  312. data/lib/{rails/generators → generators}/alchemy/site_layouts/templates/layout.html.haml +0 -0
  313. data/lib/{rails/generators → generators}/alchemy/site_layouts/templates/layout.html.slim +0 -0
  314. data/lib/{rails/generators → generators}/alchemy/views/views_generator.rb +7 -6
  315. data/lib/kaminari/scoped_pagination_url_helper.rb +1 -0
  316. data/lib/tasks/alchemy/db.rake +3 -19
  317. data/lib/tasks/alchemy/install.rake +3 -2
  318. data/lib/tasks/alchemy/tidy.rake +9 -8
  319. data/lib/tasks/alchemy/upgrade.rake +28 -105
  320. data/package.json +45 -0
  321. data/package/admin.js +14 -0
  322. data/package/src/__tests__/i18n.spec.js +70 -0
  323. data/package/src/i18n.js +48 -0
  324. data/package/src/node_tree.js +72 -0
  325. data/package/src/translations.js +32 -0
  326. data/package/src/utils/__tests__/ajax.spec.js +124 -0
  327. data/package/src/utils/__tests__/events.spec.js +38 -0
  328. data/package/src/utils/ajax.js +48 -0
  329. data/package/src/utils/events.js +16 -0
  330. data/vendor/assets/fonts/fa-regular-400.eot +0 -0
  331. data/vendor/assets/fonts/fa-regular-400.svg +798 -358
  332. data/vendor/assets/fonts/fa-regular-400.ttf +0 -0
  333. data/vendor/assets/fonts/fa-regular-400.woff +0 -0
  334. data/vendor/assets/fonts/fa-regular-400.woff2 +0 -0
  335. data/vendor/assets/fonts/fa-solid-900.eot +0 -0
  336. data/vendor/assets/fonts/fa-solid-900.svg +4933 -1408
  337. data/vendor/assets/fonts/fa-solid-900.ttf +0 -0
  338. data/vendor/assets/fonts/fa-solid-900.woff +0 -0
  339. data/vendor/assets/fonts/fa-solid-900.woff2 +0 -0
  340. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js +1 -2
  341. data/vendor/assets/stylesheets/fontawesome/_core.scss +5 -0
  342. data/vendor/assets/stylesheets/fontawesome/_fixed-width.scss +1 -1
  343. data/vendor/assets/stylesheets/fontawesome/_icons.scss +651 -2
  344. data/vendor/assets/stylesheets/fontawesome/_mixins.scss +0 -1
  345. data/vendor/assets/stylesheets/fontawesome/_rotated-flipped.scss +3 -2
  346. data/vendor/assets/stylesheets/fontawesome/_stacked.scss +1 -1
  347. data/vendor/assets/stylesheets/fontawesome/_variables.scss +662 -9
  348. data/vendor/assets/stylesheets/fontawesome/fontawesome.scss +2 -2
  349. data/vendor/assets/stylesheets/fontawesome/regular.scss +23 -0
  350. data/vendor/assets/stylesheets/fontawesome/solid.scss +24 -0
  351. metadata +131 -83
  352. data/app/assets/javascripts/alchemy/alchemy.i18n.js.coffee +0 -32
  353. data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +0 -29
  354. data/app/helpers/alchemy/essences_helper.rb +0 -119
  355. data/app/models/concerns/alchemy/content_touching.rb +0 -23
  356. data/app/serializers/alchemy/legacy_element_serializer.rb +0 -15
  357. data/app/views/alchemy/admin/contents/_missing.html.erb +0 -17
  358. data/app/views/alchemy/admin/pages/_menu_fields.html.erb +0 -33
  359. data/app/views/alchemy/admin/pages/configure_external.html.erb +0 -32
  360. data/app/views/alchemy/elements/_editor_not_found.html.erb +0 -4
  361. data/app/views/alchemy/navigation/_image_link.html.erb +0 -14
  362. data/app/views/alchemy/navigation/_link.html.erb +0 -19
  363. data/app/views/alchemy/navigation/_renderer.html.erb +0 -29
  364. data/db/migrate/20180226123013_alchemy_four_point_zero.rb +0 -363
  365. data/db/migrate/20180227224537_migrate_tags_to_gutentag.rb +0 -41
  366. data/db/migrate/20180519204655_add_fixed_to_alchemy_elements.rb +0 -6
  367. data/db/migrate/20191016073858_create_alchemy_essence_pages.rb +0 -8
  368. data/db/migrate/20191029212236_create_alchemy_nodes.rb +0 -24
  369. data/db/migrate/20200226081535_add_site_id_to_alchemy_nodes.rb +0 -15
  370. data/lib/alchemy/ssl_protection.rb +0 -32
  371. data/lib/alchemy/tasks/helpers.rb +0 -81
  372. data/lib/alchemy/test_support/controller_requests.rb +0 -93
  373. data/lib/alchemy/upgrader/four_point_four.rb +0 -52
  374. data/lib/alchemy/upgrader/four_point_one.rb +0 -42
  375. data/lib/alchemy/upgrader/four_point_two.rb +0 -85
  376. data/lib/alchemy/upgrader/tasks/cells_migration.rb +0 -43
  377. data/lib/alchemy/upgrader/tasks/cells_upgrader.rb +0 -148
  378. data/lib/alchemy/upgrader/tasks/element_partial_name_variable_updater.rb +0 -28
  379. data/lib/alchemy/upgrader/tasks/harden_acts_as_taggable_on_migrations.rb +0 -27
  380. data/lib/alchemy/upgrader/tasks/picture_gallery_migration.rb +0 -65
  381. data/lib/alchemy/upgrader/tasks/picture_gallery_upgrader.rb +0 -210
  382. data/lib/rails/generators/alchemy/essence/templates/editor.html.erb +0 -15
  383. data/lib/rails/generators/alchemy/install/install_generator.rb +0 -60
  384. data/lib/tasks/alchemy/convert.rake +0 -95
  385. data/vendor/assets/stylesheets/fontawesome/fa-regular.scss +0 -22
  386. data/vendor/assets/stylesheets/fontawesome/fa-solid.scss +0 -23
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support'
4
- require 'active_support/core_ext'
5
- require 'active_support/inflector'
3
+ require "active_support"
4
+ require "active_support/core_ext"
5
+ require "active_support/inflector"
6
6
 
7
7
  module Alchemy
8
8
  # = Alchemy::Resource
@@ -101,8 +101,8 @@ module Alchemy
101
101
  attr_accessor :resource_relations, :model_associations
102
102
  attr_reader :model
103
103
 
104
- DEFAULT_SKIPPED_ATTRIBUTES = %w(id updated_at created_at creator_id updater_id)
105
- DEFAULT_SKIPPED_ASSOCIATIONS = %w(creator updater)
104
+ DEFAULT_SKIPPED_ATTRIBUTES = %w(id created_at creator_id)
105
+ DEFAULT_SKIPPED_ASSOCIATIONS = %w(creator)
106
106
  SEARCHABLE_COLUMN_TYPES = [:string, :text]
107
107
 
108
108
  def initialize(controller_path, module_definition = nil, custom_model = nil)
@@ -113,13 +113,14 @@ module Alchemy
113
113
  if !model.respond_to?(:reflect_on_all_associations)
114
114
  raise MissingActiveRecordAssociation
115
115
  end
116
+
116
117
  store_model_associations
117
118
  map_relations
118
119
  end
119
120
  end
120
121
 
121
122
  def resource_array
122
- @_resource_array ||= controller_path_array.reject { |el| el == 'admin' }
123
+ @_resource_array ||= controller_path_array.reject { |el| el == "admin" }
123
124
  end
124
125
 
125
126
  def resources_name
@@ -138,7 +139,7 @@ module Alchemy
138
139
  @_namespaced_resources_name ||= begin
139
140
  resource_name_array = resource_array.dup
140
141
  resource_name_array.delete(engine_name) if in_engine?
141
- resource_name_array.join('_')
142
+ resource_name_array.join("_")
142
143
  end
143
144
  end
144
145
 
@@ -152,6 +153,7 @@ module Alchemy
152
153
  #
153
154
  def model_association_names
154
155
  return unless model_associations
156
+
155
157
  model_associations.map do |assoc|
156
158
  assoc.name.to_sym
157
159
  end
@@ -160,14 +162,22 @@ module Alchemy
160
162
  def attributes
161
163
  @_attributes ||= model.columns.collect do |col|
162
164
  next if skipped_attributes.include?(col.name)
165
+
163
166
  {
164
167
  name: col.name,
165
168
  type: resource_column_type(col),
166
- relation: resource_relation(col.name)
169
+ relation: resource_relation(col.name),
167
170
  }.delete_if { |_k, v| v.nil? }
168
171
  end.compact
169
172
  end
170
173
 
174
+ def sorted_attributes
175
+ @_sorted_attributes ||= attributes.
176
+ sort_by { |attr| attr[:name] == "name" ? 0 : 1 }.
177
+ sort_by! { |attr| attr[:type] == :boolean ? 1 : 0 }.
178
+ sort_by! { |attr| attr[:name] == "updated_at" ? 1 : 0 }
179
+ end
180
+
171
181
  def editable_attributes
172
182
  attributes.reject { |h| restricted_attributes.map(&:to_s).include?(h[:name].to_s) }
173
183
  end
@@ -197,7 +207,7 @@ module Alchemy
197
207
  end
198
208
 
199
209
  def engine_name
200
- @module_definition && @module_definition['engine_name']
210
+ @module_definition && @module_definition["engine_name"]
201
211
  end
202
212
 
203
213
  # Returns a help text for resource's form
@@ -254,16 +264,16 @@ module Alchemy
254
264
  def searchable_relation_attribute(attribute)
255
265
  {
256
266
  name: "#{attribute[:relation][:model_association].name}_#{attribute[:relation][:attr_method]}",
257
- type: attribute[:relation][:attr_type]
267
+ type: attribute[:relation][:attr_type],
258
268
  }
259
269
  end
260
270
 
261
271
  def guess_model_from_controller_path
262
- resource_array.join('/').classify.constantize
272
+ resource_array.join("/").classify.constantize
263
273
  end
264
274
 
265
275
  def controller_path_array
266
- @controller_path.split('/')
276
+ @controller_path.split("/")
267
277
  end
268
278
 
269
279
  def namespace_diff
@@ -286,7 +296,7 @@ module Alchemy
286
296
  def map_relations
287
297
  self.resource_relations = {}
288
298
  model.alchemy_resource_relations.each do |name, options|
289
- name = name.to_s.gsub(/_id$/, '') # ensure that we don't have an id
299
+ name = name.to_s.gsub(/_id$/, "") # ensure that we don't have an id
290
300
  association = association_from_relation_name(name)
291
301
  foreign_key = association.options[:foreign_key] || "#{association.name}_id".to_sym
292
302
  resource_relations[foreign_key] = options.merge(model_association: association, name: name)
@@ -104,30 +104,24 @@ module Alchemy
104
104
  options = {hint: resource_handler.help_text_for(attribute)}
105
105
  input_type = attribute[:type].to_s
106
106
  case input_type
107
- when 'boolean'
107
+ when "boolean"
108
108
  options
109
- when 'date', 'time', 'datetime'
109
+ when "date", "time", "datetime"
110
110
  date = resource_instance_variable.send(attribute[:name]) || Time.current
111
111
  options.merge(
112
- as: 'string',
112
+ as: "string",
113
113
  input_html: {
114
- 'data-datepicker-type' => input_type,
115
- value: date ? date.iso8601 : nil
116
- }
114
+ "data-datepicker-type" => input_type,
115
+ value: date ? date.iso8601 : nil,
116
+ },
117
117
  )
118
- when 'text'
119
- options.merge(as: 'text', input_html: {rows: 4})
118
+ when "text"
119
+ options.merge(as: "text", input_html: {rows: 4})
120
120
  else
121
- options.merge(as: 'string')
121
+ options.merge(as: "string")
122
122
  end
123
123
  end
124
124
 
125
- # Renders the human model name with a count as h1 header
126
- def resources_header
127
- Alchemy::Deprecation.warn "resources_header is deprecated. Render 'alchemy/admin/resources/table_header' partial instead."
128
- render 'alchemy/admin/resources/table_header'
129
- end
130
-
131
125
  # Returns true if the resource contains any relations
132
126
  def contains_relations?
133
127
  resource_handler.resource_relations.present?
@@ -171,7 +165,7 @@ module Alchemy
171
165
  def render_resources
172
166
  render partial: resource_name, collection: resources_instance_variable
173
167
  rescue ActionView::MissingTemplate
174
- render partial: 'resource', collection: resources_instance_variable
168
+ render partial: "resource", collection: resources_instance_variable
175
169
  end
176
170
 
177
171
  def resource_has_tags
@@ -185,8 +179,8 @@ module Alchemy
185
179
  def resource_filter_select
186
180
  resource_model.alchemy_resource_filters.map do |filter_scope|
187
181
  [
188
- Alchemy.t(filter_scope.to_sym, scope: ['resources', resource_name, 'filters']),
189
- filter_scope
182
+ Alchemy.t(filter_scope.to_sym, scope: ["resources", resource_name, "filters"]),
183
+ filter_scope,
190
184
  ]
191
185
  end
192
186
  end
@@ -34,7 +34,7 @@ module Alchemy
34
34
  def no_rails_route?
35
35
  return true if !%w(development test).include?(Rails.env)
36
36
 
37
- (@params['urlname'] =~ /\Arails\//).nil?
37
+ (@params["urlname"] =~ /\Arails\//).nil?
38
38
  end
39
39
  end
40
40
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "alchemy/shell"
2
3
 
3
4
  module Alchemy
@@ -23,11 +24,14 @@ module Alchemy
23
24
 
24
25
  def try_seed_pages
25
26
  return unless page_seeds_file.file?
27
+
26
28
  if Alchemy::Page.exists?
27
29
  desc "Seeding Alchemy pages"
28
30
  log "There are already pages present in your database. " \
29
31
  "Please use `rake db:reset' if you want to rebuild your database.", :skip
30
32
  else
33
+ create_default_site! unless Alchemy::Site.default
34
+ create_default_language! unless Alchemy::Language.default
31
35
  seed_pages if contentpages.present?
32
36
  seed_layoutpages if layoutpages.present?
33
37
  end
@@ -41,9 +45,8 @@ module Alchemy
41
45
 
42
46
  contentpages.each do |page|
43
47
  create_page(page, {
44
- parent: Alchemy::Page.root,
45
48
  language: Alchemy::Language.default,
46
- language_root: true
49
+ language_root: true,
47
50
  })
48
51
  end
49
52
  end
@@ -51,12 +54,8 @@ module Alchemy
51
54
  def seed_layoutpages
52
55
  desc "Seeding Alchemy layout pages from #{page_seeds_file}"
53
56
  language = Alchemy::Language.default
54
- layout_root = Alchemy::Page.find_or_create_layout_root_for(language.id)
55
57
  layoutpages.each do |page|
56
- create_page(page, {
57
- parent: layout_root,
58
- language: language
59
- })
58
+ create_page(page, { language: language })
60
59
  end
61
60
  end
62
61
 
@@ -66,7 +65,7 @@ module Alchemy
66
65
  if Alchemy.user_class.exists?
67
66
  log "There are already users present in your database. " \
68
67
  "Please use `rake db:reset' if you want to rebuild your database.", :skip
69
- return false
68
+ false
70
69
  else
71
70
  users = YAML.load_file(user_seeds_file)
72
71
  users.each do |draft|
@@ -79,7 +78,7 @@ module Alchemy
79
78
  private
80
79
 
81
80
  def page_seeds_file
82
- @_page_seeds_file ||= Rails.root.join('db', 'seeds', 'alchemy', 'pages.yml')
81
+ @_page_seeds_file ||= Rails.root.join("db", "seeds", "alchemy", "pages.yml")
83
82
  end
84
83
 
85
84
  def page_yml
@@ -87,23 +86,52 @@ module Alchemy
87
86
  end
88
87
 
89
88
  def contentpages
90
- page_yml.reject { |p| p['layoutpage'] }
89
+ page_yml.reject { |p| p["layoutpage"] }
91
90
  end
92
91
 
93
92
  def layoutpages
94
- page_yml.select { |p| p['layoutpage'] }
93
+ page_yml.select { |p| p["layoutpage"] }
95
94
  end
96
95
 
97
96
  def user_seeds_file
98
- @_user_seeds_file ||= Rails.root.join('db', 'seeds', 'alchemy', 'users.yml')
97
+ @_user_seeds_file ||= Rails.root.join("db", "seeds", "alchemy", "users.yml")
99
98
  end
100
99
 
101
100
  def create_page(draft, attributes = {})
102
- children = draft.delete('children') || []
101
+ children = draft.delete("children") || []
103
102
  page = Alchemy::Page.create!(draft.merge(attributes))
104
103
  log "Created page: #{page.name}"
105
104
  children.each do |child|
106
- create_page(child, parent: page)
105
+ create_page(child, parent: page, language: page.language)
106
+ end
107
+ end
108
+
109
+ # If no languages are present, create a default language based
110
+ # on the host app's Alchemy configuration.
111
+ def create_default_language!
112
+ default_language = Alchemy::Config.get(:default_language)
113
+ if default_language
114
+ Alchemy::Language.create!(
115
+ name: default_language["name"],
116
+ language_code: default_language["code"],
117
+ locale: default_language["code"],
118
+ frontpage_name: default_language["frontpage_name"],
119
+ page_layout: default_language["page_layout"],
120
+ public: true,
121
+ default: true,
122
+ site: Alchemy::Site.default,
123
+ )
124
+ else
125
+ raise DefaultLanguageNotFoundError
126
+ end
127
+ end
128
+
129
+ def create_default_site!
130
+ default_site = Alchemy::Config.get(:default_site)
131
+ if default_site
132
+ Alchemy::Site.create!(name: default_site["name"], host: default_site["host"])
133
+ else
134
+ raise DefaultSiteNotFoundError
107
135
  end
108
136
  end
109
137
  end
@@ -1,10 +1,18 @@
1
- require 'thor/shell/color'
1
+ # frozen_string_literal: true
2
+ require "thor/shell/color"
2
3
 
3
4
  module Alchemy
4
5
  # Provides methods for collecting sentences and displaying them
5
6
  # in a list on the shell / log
6
7
  #
7
8
  module Shell
9
+ COLORS = {
10
+ clear: Thor::Shell::Color::CLEAR,
11
+ green: Thor::Shell::Color::GREEN,
12
+ red: Thor::Shell::Color::RED,
13
+ yellow: Thor::Shell::Color::YELLOW,
14
+ }.freeze
15
+
8
16
  def self.silence!
9
17
  @silenced = true
10
18
  end
@@ -20,11 +28,11 @@ module Alchemy
20
28
  def desc(message)
21
29
  unless Alchemy::Shell.silenced?
22
30
  puts "\n#{message}"
23
- puts "#{'-' * message.length}\n"
31
+ puts "#{"-" * message.length}\n"
24
32
  end
25
33
  end
26
34
 
27
- def todo(todo, title = '')
35
+ def todo(todo, title = "")
28
36
  add_todo [title, todo]
29
37
  end
30
38
 
@@ -56,7 +64,7 @@ module Alchemy
56
64
  todos.each_with_index do |todo, i|
57
65
  title = "\n#{i + 1}. #{todo[0]}"
58
66
  log title, :message
59
- puts '=' * title.length
67
+ puts "=" * title.length
60
68
  puts ""
61
69
  log todo[1], :message
62
70
  end
@@ -96,12 +104,7 @@ module Alchemy
96
104
  # @return [String]
97
105
  #
98
106
  def color(name)
99
- color_const = name.to_s.upcase
100
- if Thor::Shell::Color.const_defined?(color_const)
101
- "Thor::Shell::Color::#{color_const}".constantize
102
- else
103
- ""
104
- end
107
+ COLORS[name]
105
108
  end
106
109
  end
107
110
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Alchemy
2
3
  # ActsAsTaggableOn to Gutentag interface compatibility module
3
4
  # Include this module to add tagging support to your model.
@@ -1,4 +1,5 @@
1
- require 'alchemy/shell'
1
+ # frozen_string_literal: true
2
+ require "alchemy/shell"
2
3
 
3
4
  module Alchemy
4
5
  class Tidy
@@ -52,7 +53,7 @@ module Alchemy
52
53
  end
53
54
  if orphaned_elements.any?
54
55
  log "Found #{orphaned_elements.size} orphaned elements"
55
- destroy_orphaned_records(orphaned_elements, 'element')
56
+ destroy_orphaned_records(orphaned_elements, "element")
56
57
  else
57
58
  log "No orphaned elements found", :skip
58
59
  end
@@ -71,7 +72,7 @@ module Alchemy
71
72
  end
72
73
  if orphaned_contents.any?
73
74
  log "Found #{orphaned_contents.size} orphaned contents"
74
- destroy_orphaned_records(orphaned_contents, 'content')
75
+ destroy_orphaned_records(orphaned_contents, "content")
75
76
  else
76
77
  log "No orphaned contents found", :skip
77
78
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Alchemy
2
3
  module TestSupport
3
4
  # Allows you to stub the Alchemy configuration in your specs
@@ -1,36 +1,36 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'shoulda-matchers'
4
- require 'alchemy/test_support/factories/page_factory'
5
- require 'alchemy/test_support/factories/element_factory'
6
- require 'alchemy/test_support/factories/content_factory'
3
+ require "shoulda-matchers"
4
+ require "alchemy/test_support/factories/page_factory"
5
+ require "alchemy/test_support/factories/element_factory"
6
+ require "alchemy/test_support/factories/content_factory"
7
7
 
8
8
  RSpec.shared_examples_for "an essence" do
9
9
  let(:element) { Alchemy::Element.new }
10
- let(:content) { Alchemy::Content.new(name: 'foo') }
11
- let(:content_definition) { {'name' => 'foo'} }
10
+ let(:content) { Alchemy::Content.new(name: "foo") }
11
+ let(:content_definition) { { "name" => "foo" } }
12
12
 
13
- describe 'eager loading' do
13
+ describe "eager loading" do
14
14
  before do
15
15
  2.times { described_class.create! }
16
16
  end
17
17
 
18
- it 'does not throw error if eager loaded' do
18
+ it "does not throw error if eager loaded" do
19
19
  expect {
20
20
  described_class.all.includes(:ingredient_association).to_a
21
21
  }.to_not raise_error
22
22
  end
23
23
  end
24
24
 
25
- it "touches the content after update" do
25
+ it "touches the element after save" do
26
26
  element = FactoryBot.create(:alchemy_element)
27
27
  content = FactoryBot.create(:alchemy_content, element: element, essence: essence, essence_type: essence.class.name)
28
28
 
29
- content.update_column(:updated_at, 3.days.ago)
29
+ element.update_column(:updated_at, 3.days.ago)
30
30
  content.essence.update(essence.ingredient_column.to_sym => ingredient_value)
31
31
 
32
- content.reload
33
- expect(content.updated_at).to be_within(3.seconds).of(Time.current)
32
+ element.reload
33
+ expect(element.updated_at).to be_within(3.seconds).of(Time.current)
34
34
  end
35
35
 
36
36
  it "should have correct partial path" do
@@ -38,28 +38,28 @@ RSpec.shared_examples_for "an essence" do
38
38
  expect(essence.to_partial_path).to eq("alchemy/essences/#{underscored_essence}_view")
39
39
  end
40
40
 
41
- describe '#definition' do
41
+ describe "#definition" do
42
42
  subject { essence.definition }
43
43
 
44
- context 'without element' do
44
+ context "without element" do
45
45
  it { is_expected.to eq({}) }
46
46
  end
47
47
 
48
- context 'with element' do
48
+ context "with element" do
49
49
  before do
50
50
  expect(essence).to receive(:element).at_least(:once).and_return(element)
51
51
  end
52
52
 
53
- context 'but without content definitions' do
53
+ context "but without content definitions" do
54
54
  it { is_expected.to eq({}) }
55
55
  end
56
56
 
57
- context 'and content definitions' do
57
+ context "and content definitions" do
58
58
  before do
59
59
  allow(essence).to receive(:content).and_return(content)
60
60
  end
61
61
 
62
- context 'containing the content name' do
62
+ context "containing the content name" do
63
63
  before do
64
64
  expect(element).to receive(:content_definitions).at_least(:once).and_return([content_definition])
65
65
  end
@@ -69,7 +69,7 @@ RSpec.shared_examples_for "an essence" do
69
69
  end
70
70
  end
71
71
 
72
- context 'not containing the content name' do
72
+ context "not containing the content name" do
73
73
  before do
74
74
  expect(element).to receive(:content_definitions).at_least(:once).and_return([])
75
75
  end
@@ -80,200 +80,200 @@ RSpec.shared_examples_for "an essence" do
80
80
  end
81
81
  end
82
82
 
83
- describe '#ingredient=' do
84
- it 'should set the value to ingredient column' do
83
+ describe "#ingredient=" do
84
+ it "should set the value to ingredient column" do
85
85
  essence.ingredient = ingredient_value
86
86
  expect(essence.ingredient).to eq ingredient_value
87
87
  end
88
88
  end
89
89
 
90
- describe 'validations' do
91
- context 'without essence definition in elements.yml' do
92
- it 'should return an empty array' do
90
+ describe "validations" do
91
+ context "without essence definition in elements.yml" do
92
+ it "should return an empty array" do
93
93
  allow(essence).to receive(:definition).and_return nil
94
94
  expect(essence.validations).to eq([])
95
95
  end
96
96
  end
97
97
 
98
- context 'without validations defined in essence definition in elements.yml' do
99
- it 'should return an empty array' do
100
- allow(essence).to receive(:definition).and_return({name: 'test', type: 'EssenceText'})
98
+ context "without validations defined in essence definition in elements.yml" do
99
+ it "should return an empty array" do
100
+ allow(essence).to receive(:definition).and_return({ name: "test", type: "EssenceText" })
101
101
  expect(essence.validations).to eq([])
102
102
  end
103
103
  end
104
104
 
105
- describe 'presence' do
106
- context 'with string given as validation type' do
105
+ describe "presence" do
106
+ context "with string given as validation type" do
107
107
  before do
108
- allow(essence).to receive(:definition).and_return({'validate' => ['presence']})
108
+ allow(essence).to receive(:definition).and_return({ "validate" => ["presence"] })
109
109
  end
110
110
 
111
- context 'when the ingredient column is empty' do
111
+ context "when the ingredient column is empty" do
112
112
  before do
113
113
  essence.update(essence.ingredient_column.to_sym => nil)
114
114
  end
115
115
 
116
- it 'should not be valid' do
116
+ it "should not be valid" do
117
117
  expect(essence).to_not be_valid
118
118
  end
119
119
  end
120
120
 
121
- context 'when the ingredient column is not nil' do
121
+ context "when the ingredient column is not nil" do
122
122
  before do
123
123
  essence.update(essence.ingredient_column.to_sym => ingredient_value)
124
124
  end
125
125
 
126
- it 'should be valid' do
126
+ it "should be valid" do
127
127
  expect(essence).to be_valid
128
128
  end
129
129
  end
130
130
  end
131
131
 
132
- context 'with hash given as validation type' do
133
- context 'where the value is true' do
132
+ context "with hash given as validation type" do
133
+ context "where the value is true" do
134
134
  before do
135
- allow(essence).to receive(:definition).and_return({'validate' => [{'presence' => true}]})
135
+ allow(essence).to receive(:definition).and_return({ "validate" => [{ "presence" => true }] })
136
136
  end
137
137
 
138
- context 'when the ingredient column is empty' do
138
+ context "when the ingredient column is empty" do
139
139
  before do
140
140
  essence.update(essence.ingredient_column.to_sym => nil)
141
141
  end
142
142
 
143
- it 'should not be valid' do
143
+ it "should not be valid" do
144
144
  expect(essence).to_not be_valid
145
145
  end
146
146
  end
147
147
 
148
- context 'when the ingredient column is not nil' do
148
+ context "when the ingredient column is not nil" do
149
149
  before do
150
150
  essence.update(essence.ingredient_column.to_sym => ingredient_value)
151
151
  end
152
152
 
153
- it 'should be valid' do
153
+ it "should be valid" do
154
154
  expect(essence).to be_valid
155
155
  end
156
156
  end
157
157
  end
158
158
 
159
- context 'where the value is false' do
159
+ context "where the value is false" do
160
160
  before do
161
- allow(essence).to receive(:definition).and_return({'validate' => [{'presence' => false}]})
161
+ allow(essence).to receive(:definition).and_return({ "validate" => [{ "presence" => false }] })
162
162
  end
163
163
 
164
- it 'should be valid' do
164
+ it "should be valid" do
165
165
  expect(essence).to be_valid
166
166
  end
167
167
  end
168
168
  end
169
169
  end
170
170
 
171
- describe 'uniqueness' do
171
+ describe "uniqueness" do
172
172
  before do
173
- allow(essence).to receive(:element).and_return(FactoryBot.build_stubbed(:alchemy_element))
173
+ allow(essence).to receive(:element).and_return(FactoryBot.create(:alchemy_element))
174
174
  essence.update(essence.ingredient_column.to_sym => ingredient_value)
175
175
  end
176
176
 
177
- context 'with string given as validation type' do
177
+ context "with string given as validation type" do
178
178
  before do
179
- expect(essence).to receive(:definition).at_least(:once).and_return({'validate' => ['uniqueness']})
179
+ expect(essence).to receive(:definition).at_least(:once).and_return({ "validate" => ["uniqueness"] })
180
180
  end
181
181
 
182
- context 'when a duplicate exists' do
182
+ context "when a duplicate exists" do
183
183
  before do
184
184
  allow(essence).to receive(:duplicates).and_return([essence.dup])
185
185
  end
186
186
 
187
- it 'should not be valid' do
187
+ it "should not be valid" do
188
188
  expect(essence).to_not be_valid
189
189
  end
190
190
 
191
- context 'when validated essence is not public' do
191
+ context "when validated essence is not public" do
192
192
  before do
193
193
  expect(essence).to receive(:public?).and_return(false)
194
194
  end
195
195
 
196
- it 'should be valid' do
196
+ it "should be valid" do
197
197
  expect(essence).to be_valid
198
198
  end
199
199
  end
200
200
  end
201
201
 
202
- context 'when no duplicate exists' do
202
+ context "when no duplicate exists" do
203
203
  before do
204
204
  expect(essence).to receive(:duplicates).and_return([])
205
205
  end
206
206
 
207
- it 'should be valid' do
207
+ it "should be valid" do
208
208
  expect(essence).to be_valid
209
209
  end
210
210
  end
211
211
  end
212
212
 
213
- context 'with hash given as validation type' do
214
- context 'where the value is true' do
213
+ context "with hash given as validation type" do
214
+ context "where the value is true" do
215
215
  before do
216
- expect(essence).to receive(:definition).at_least(:once).and_return({'validate' => [{'uniqueness' => true}]})
216
+ expect(essence).to receive(:definition).at_least(:once).and_return({ "validate" => [{ "uniqueness" => true }] })
217
217
  end
218
218
 
219
- context 'when a duplicate exists' do
219
+ context "when a duplicate exists" do
220
220
  before do
221
221
  allow(essence).to receive(:duplicates).and_return([essence.dup])
222
222
  end
223
223
 
224
- it 'should not be valid' do
224
+ it "should not be valid" do
225
225
  expect(essence).to_not be_valid
226
226
  end
227
227
 
228
- context 'when validated essence is not public' do
228
+ context "when validated essence is not public" do
229
229
  before do
230
230
  expect(essence).to receive(:public?).and_return(false)
231
231
  end
232
232
 
233
- it 'should be valid' do
233
+ it "should be valid" do
234
234
  expect(essence).to be_valid
235
235
  end
236
236
  end
237
237
  end
238
238
 
239
- context 'when no duplicate exists' do
239
+ context "when no duplicate exists" do
240
240
  before do
241
241
  expect(essence).to receive(:duplicates).and_return([])
242
242
  end
243
243
 
244
- it 'should be valid' do
244
+ it "should be valid" do
245
245
  expect(essence).to be_valid
246
246
  end
247
247
  end
248
248
  end
249
249
 
250
- context 'where the value is false' do
250
+ context "where the value is false" do
251
251
  before do
252
- allow(essence).to receive(:definition).and_return({'validate' => [{'uniqueness' => false}]})
252
+ allow(essence).to receive(:definition).and_return({ "validate" => [{ "uniqueness" => false }] })
253
253
  end
254
254
 
255
- it 'should be valid' do
255
+ it "should be valid" do
256
256
  expect(essence).to be_valid
257
257
  end
258
258
  end
259
259
  end
260
260
  end
261
261
 
262
- describe '#acts_as_essence?' do
263
- it 'should return true' do
262
+ describe "#acts_as_essence?" do
263
+ it "should return true" do
264
264
  expect(essence.acts_as_essence?).to be_truthy
265
265
  end
266
266
  end
267
267
  end
268
268
 
269
- context 'delegations' do
269
+ context "delegations" do
270
270
  it { should delegate_method(:restricted?).to(:page) }
271
271
  it { should delegate_method(:trashed?).to(:element) }
272
- it { should delegate_method(:public?).to(:element) }
272
+ it { should delegate_method(:public?).to(:element) }
273
273
  end
274
274
 
275
- describe 'essence relations' do
276
- let(:page) { FactoryBot.create(:alchemy_page, :restricted) }
275
+ describe "essence relations" do
276
+ let(:page) { FactoryBot.create(:alchemy_page, :restricted) }
277
277
  let(:element) { FactoryBot.create(:alchemy_element) }
278
278
 
279
279
  it "registers itself on page as essence relation" do