alchemy_cms 4.6.1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (386) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +33 -1
  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 +30 -9
  8. data/CHANGELOG.md +102 -1
  9. data/Gemfile +24 -22
  10. data/README.md +32 -20
  11. data/Rakefile +11 -8
  12. data/alchemy_cms.gemspec +6 -5
  13. data/app/assets/javascripts/alchemy/admin.js +1 -5
  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.page_sorter.js +17 -17
  17. data/app/assets/javascripts/alchemy/node_select.js +39 -0
  18. data/app/assets/javascripts/alchemy/templates/index.js +1 -0
  19. data/app/assets/javascripts/alchemy/templates/node.hbs +16 -0
  20. data/app/assets/stylesheets/alchemy/admin.scss +3 -2
  21. data/app/assets/stylesheets/alchemy/base.scss +0 -1
  22. data/app/assets/stylesheets/alchemy/elements.scss +1 -1
  23. data/app/assets/stylesheets/alchemy/forms.scss +5 -0
  24. data/app/assets/stylesheets/alchemy/navigation.scss +1 -0
  25. data/app/assets/stylesheets/alchemy/node-select.scss +43 -0
  26. data/app/assets/stylesheets/alchemy/nodes.scss +1 -1
  27. data/app/assets/stylesheets/alchemy/sitemap.scss +5 -1
  28. data/app/assets/stylesheets/alchemy/tables.scss +1 -24
  29. data/app/assets/stylesheets/alchemy/tags.scss +2 -2
  30. data/app/controllers/alchemy/admin/attachments_controller.rb +8 -7
  31. data/app/controllers/alchemy/admin/base_controller.rb +13 -33
  32. data/app/controllers/alchemy/admin/clipboard_controller.rb +5 -4
  33. data/app/controllers/alchemy/admin/contents_controller.rb +1 -2
  34. data/app/controllers/alchemy/admin/dashboard_controller.rb +10 -9
  35. data/app/controllers/alchemy/admin/elements_controller.rb +20 -20
  36. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +12 -14
  37. data/app/controllers/alchemy/admin/languages_controller.rb +35 -2
  38. data/app/controllers/alchemy/admin/layoutpages_controller.rb +5 -2
  39. data/app/controllers/alchemy/admin/nodes_controller.rb +5 -4
  40. data/app/controllers/alchemy/admin/pages_controller.rb +51 -63
  41. data/app/controllers/alchemy/admin/pictures_controller.rb +16 -16
  42. data/app/controllers/alchemy/admin/resources_controller.rb +21 -13
  43. data/app/controllers/alchemy/admin/sites_controller.rb +18 -0
  44. data/app/controllers/alchemy/admin/styleguide_controller.rb +1 -0
  45. data/app/controllers/alchemy/admin/tags_controller.rb +5 -3
  46. data/app/controllers/alchemy/admin/trash_controller.rb +6 -6
  47. data/app/controllers/alchemy/api/base_controller.rb +2 -2
  48. data/app/controllers/alchemy/api/contents_controller.rb +4 -4
  49. data/app/controllers/alchemy/api/elements_controller.rb +8 -8
  50. data/app/controllers/alchemy/api/nodes_controller.rb +37 -1
  51. data/app/controllers/alchemy/api/pages_controller.rb +14 -23
  52. data/app/controllers/alchemy/attachments_controller.rb +5 -5
  53. data/app/controllers/alchemy/base_controller.rb +10 -9
  54. data/app/controllers/alchemy/messages_controller.rb +16 -23
  55. data/app/controllers/alchemy/pages_controller.rb +13 -11
  56. data/app/controllers/concerns/alchemy/admin/archive_overlay.rb +3 -2
  57. data/app/controllers/concerns/alchemy/admin/current_language.rb +23 -0
  58. data/app/controllers/concerns/alchemy/admin/uploader_responses.rb +5 -5
  59. data/app/controllers/concerns/alchemy/legacy_page_redirects.rb +4 -4
  60. data/app/controllers/concerns/alchemy/page_redirects.rb +2 -9
  61. data/app/controllers/concerns/alchemy/site_redirects.rb +2 -2
  62. data/app/decorators/alchemy/element_editor.rb +39 -0
  63. data/app/helpers/alchemy/admin/attachments_helper.rb +6 -6
  64. data/app/helpers/alchemy/admin/base_helper.rb +38 -35
  65. data/app/helpers/alchemy/admin/contents_helper.rb +3 -3
  66. data/app/helpers/alchemy/admin/elements_helper.rb +3 -88
  67. data/app/helpers/alchemy/admin/essences_helper.rb +8 -117
  68. data/app/helpers/alchemy/admin/form_helper.rb +1 -1
  69. data/app/helpers/alchemy/admin/navigation_helper.rb +24 -23
  70. data/app/helpers/alchemy/admin/pages_helper.rb +4 -4
  71. data/app/helpers/alchemy/admin/pictures_helper.rb +4 -6
  72. data/app/helpers/alchemy/admin/tags_helper.rb +8 -7
  73. data/app/helpers/alchemy/base_helper.rb +13 -8
  74. data/app/helpers/alchemy/elements_block_helper.rb +2 -31
  75. data/app/helpers/alchemy/elements_helper.rb +12 -58
  76. data/app/helpers/alchemy/pages_helper.rb +24 -174
  77. data/app/helpers/alchemy/url_helper.rb +4 -3
  78. data/app/mailers/alchemy/base_mailer.rb +1 -1
  79. data/app/mailers/alchemy/messages_mailer.rb +1 -1
  80. data/app/models/alchemy/attachment.rb +24 -19
  81. data/app/models/alchemy/base_record.rb +2 -5
  82. data/app/models/alchemy/content.rb +33 -38
  83. data/app/models/alchemy/content/factory.rb +24 -31
  84. data/app/models/alchemy/element.rb +45 -53
  85. data/app/models/alchemy/element/definitions.rb +4 -4
  86. data/app/models/alchemy/element/element_contents.rb +9 -6
  87. data/app/models/alchemy/element/element_essences.rb +4 -3
  88. data/app/models/alchemy/element/presenters.rb +3 -2
  89. data/app/models/alchemy/element_to_page.rb +1 -1
  90. data/app/models/alchemy/essence_boolean.rb +1 -3
  91. data/app/models/alchemy/essence_date.rb +2 -3
  92. data/app/models/alchemy/essence_file.rb +5 -5
  93. data/app/models/alchemy/essence_html.rb +1 -3
  94. data/app/models/alchemy/essence_link.rb +1 -3
  95. data/app/models/alchemy/essence_node.rb +18 -0
  96. data/app/models/alchemy/essence_page.rb +3 -16
  97. data/app/models/alchemy/essence_picture.rb +18 -17
  98. data/app/models/alchemy/essence_picture_view.rb +7 -6
  99. data/app/models/alchemy/essence_richtext.rb +1 -3
  100. data/app/models/alchemy/essence_select.rb +1 -3
  101. data/app/models/alchemy/essence_text.rb +0 -2
  102. data/app/models/alchemy/folded_page.rb +1 -0
  103. data/app/models/alchemy/language.rb +21 -35
  104. data/app/models/alchemy/language/code.rb +4 -4
  105. data/app/models/alchemy/legacy_page_url.rb +1 -1
  106. data/app/models/alchemy/message.rb +3 -3
  107. data/app/models/alchemy/node.rb +27 -4
  108. data/app/models/alchemy/page.rb +46 -127
  109. data/app/models/alchemy/page/fixed_attributes.rb +3 -2
  110. data/app/models/alchemy/page/page_elements.rb +35 -44
  111. data/app/models/alchemy/page/page_naming.rb +20 -70
  112. data/app/models/alchemy/page/page_natures.rb +7 -34
  113. data/app/models/alchemy/page/page_scopes.rb +23 -29
  114. data/app/models/alchemy/page/url_path.rb +0 -2
  115. data/app/models/alchemy/picture.rb +40 -30
  116. data/app/models/alchemy/picture/preprocessor.rb +26 -0
  117. data/app/models/alchemy/picture/transformations.rb +9 -7
  118. data/app/models/alchemy/picture/url.rb +9 -7
  119. data/app/models/alchemy/site.rb +6 -36
  120. data/app/models/alchemy/site/layout.rb +2 -2
  121. data/app/models/concerns/alchemy/touch_elements.rb +24 -0
  122. data/app/serializers/alchemy/content_serializer.rb +0 -3
  123. data/app/serializers/alchemy/essence_boolean_serializer.rb +3 -3
  124. data/app/serializers/alchemy/essence_date_serializer.rb +3 -3
  125. data/app/serializers/alchemy/essence_file_serializer.rb +4 -2
  126. data/app/serializers/alchemy/essence_html_serializer.rb +3 -3
  127. data/app/serializers/alchemy/essence_link_serializer.rb +3 -3
  128. data/app/serializers/alchemy/essence_picture_serializer.rb +5 -4
  129. data/app/serializers/alchemy/essence_richtext_serializer.rb +3 -3
  130. data/app/serializers/alchemy/essence_select_serializer.rb +3 -3
  131. data/app/serializers/alchemy/essence_text_serializer.rb +5 -4
  132. data/app/serializers/alchemy/node_serializer.rb +2 -0
  133. data/app/serializers/alchemy/page_tree_serializer.rb +9 -13
  134. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +1 -2
  135. data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +1 -2
  136. data/app/views/alchemy/admin/attachments/_files_list.html.erb +4 -4
  137. data/app/views/alchemy/admin/contents/create.js.erb +1 -3
  138. data/app/views/alchemy/admin/elements/_element.html.erb +9 -18
  139. data/app/views/alchemy/admin/elements/create.js.erb +1 -1
  140. data/app/views/alchemy/admin/elements/fold.js.erb +1 -1
  141. data/app/views/alchemy/admin/elements/index.html.erb +3 -3
  142. data/app/views/alchemy/admin/essence_files/assign.js.erb +1 -6
  143. data/app/views/alchemy/admin/essence_files/edit.html.erb +1 -1
  144. data/app/views/alchemy/admin/essence_pictures/assign.js.erb +1 -7
  145. data/app/views/alchemy/admin/essence_pictures/crop.html.erb +1 -1
  146. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +7 -7
  147. data/app/views/alchemy/admin/essence_pictures/update.js.erb +1 -1
  148. data/app/views/alchemy/admin/languages/_form.html.erb +5 -5
  149. data/app/views/alchemy/admin/languages/_table.html.erb +3 -3
  150. data/app/views/alchemy/admin/languages/edit.html.erb +1 -0
  151. data/app/views/alchemy/admin/languages/index.html.erb +23 -4
  152. data/app/views/alchemy/admin/languages/new.html.erb +1 -0
  153. data/app/views/alchemy/admin/layoutpages/index.html.erb +3 -3
  154. data/app/views/alchemy/admin/nodes/_form.html.erb +18 -15
  155. data/app/views/alchemy/admin/nodes/_node.html.erb +1 -5
  156. data/app/views/alchemy/admin/nodes/index.html.erb +3 -4
  157. data/app/views/alchemy/admin/pages/_create_language_form.html.erb +0 -8
  158. data/app/views/alchemy/admin/pages/_form.html.erb +0 -1
  159. data/app/views/alchemy/admin/pages/_new_page_form.html.erb +1 -0
  160. data/app/views/alchemy/admin/pages/_page.html.erb +11 -19
  161. data/app/views/alchemy/admin/pages/_page_infos.html.erb +0 -4
  162. data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
  163. data/app/views/alchemy/admin/pages/info.html.erb +0 -9
  164. data/app/views/alchemy/admin/pages/unlock.js.erb +13 -6
  165. data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +0 -2
  166. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +1 -5
  167. data/app/views/alchemy/admin/pictures/_overlay_picture_list.html.erb +1 -1
  168. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +1 -2
  169. data/app/views/alchemy/admin/pictures/index.html.erb +18 -3
  170. data/app/views/alchemy/admin/pictures/show.html.erb +1 -1
  171. data/app/views/alchemy/admin/resources/_resource.html.erb +1 -1
  172. data/app/views/alchemy/admin/resources/_table.html.erb +2 -2
  173. data/app/views/alchemy/admin/resources/index.html.erb +21 -22
  174. data/app/views/alchemy/admin/sites/_form.html.erb +8 -0
  175. data/app/views/alchemy/admin/sites/edit.html.erb +1 -0
  176. data/app/views/alchemy/admin/sites/index.html.erb +21 -9
  177. data/app/views/alchemy/admin/sites/new.html.erb +1 -0
  178. data/app/views/alchemy/admin/tags/index.html.erb +2 -2
  179. data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +10 -12
  180. data/app/views/alchemy/essences/_essence_date_editor.html.erb +11 -8
  181. data/app/views/alchemy/essences/_essence_file_editor.html.erb +16 -17
  182. data/app/views/alchemy/essences/_essence_file_view.html.erb +1 -1
  183. data/app/views/alchemy/essences/_essence_html_editor.html.erb +8 -5
  184. data/app/views/alchemy/essences/_essence_link_editor.html.erb +18 -15
  185. data/app/views/alchemy/essences/_essence_node_editor.html.erb +27 -0
  186. data/app/views/alchemy/essences/_essence_node_view.html.erb +1 -0
  187. data/app/views/alchemy/essences/_essence_page_editor.html.erb +14 -11
  188. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +22 -20
  189. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +10 -7
  190. data/app/views/alchemy/essences/_essence_select_editor.html.erb +12 -16
  191. data/app/views/alchemy/essences/_essence_text_editor.html.erb +18 -17
  192. data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +6 -11
  193. data/app/views/alchemy/pages/show.rss.builder +3 -2
  194. data/app/views/layouts/alchemy/admin.html.erb +1 -0
  195. data/babel.config.js +12 -0
  196. data/bin/rails +5 -4
  197. data/config/alchemy/config.yml +23 -16
  198. data/config/brakeman.ignore +1 -1
  199. data/config/initializers/assets.rb +2 -1
  200. data/config/initializers/dragonfly.rb +2 -1
  201. data/config/initializers/mime_types.rb +1 -0
  202. data/config/initializers/mini_profiler.rb +3 -2
  203. data/config/initializers/simple_form.rb +6 -6
  204. data/config/locales/alchemy.en.yml +23 -8
  205. data/config/routes.rb +25 -24
  206. data/config/spring.rb +3 -2
  207. data/db/migrate/20200226213334_alchemy_four_point_four.rb +313 -0
  208. data/db/migrate/20200423073425_create_alchemy_essence_nodes.rb +11 -0
  209. data/db/migrate/20200504210159_remove_site_id_from_nodes.rb +28 -0
  210. data/db/migrate/20200505215518_add_language_id_foreign_key_to_alchemy_pages.rb +8 -0
  211. data/db/migrate/20200511113603_add_menu_type_to_alchemy_nodes.rb +27 -0
  212. data/db/migrate/20200514091507_make_page_layoutpage_null_false.rb +6 -0
  213. data/db/migrate/20200519073500_remove_visible_from_alchemy_pages.rb +24 -0
  214. data/lib/alchemy/admin/locale.rb +3 -1
  215. data/lib/alchemy/admin/preview_url.rb +85 -0
  216. data/lib/alchemy/auth_accessors.rb +8 -7
  217. data/lib/alchemy/cache_digests/template_tracker.rb +5 -4
  218. data/lib/alchemy/config.rb +3 -5
  219. data/lib/alchemy/configuration_methods.rb +3 -1
  220. data/lib/alchemy/controller_actions.rb +6 -5
  221. data/lib/alchemy/deprecation.rb +2 -1
  222. data/lib/alchemy/elements_finder.rb +5 -5
  223. data/lib/alchemy/engine.rb +23 -8
  224. data/lib/alchemy/errors.rb +0 -7
  225. data/lib/alchemy/essence.rb +17 -16
  226. data/lib/alchemy/filetypes.rb +5 -5
  227. data/lib/alchemy/forms/builder.rb +4 -4
  228. data/lib/alchemy/hints.rb +1 -1
  229. data/lib/alchemy/i18n.rb +2 -1
  230. data/lib/alchemy/install/tasks.rb +41 -0
  231. data/lib/alchemy/modules.rb +12 -12
  232. data/lib/alchemy/name_conversions.rb +5 -5
  233. data/lib/alchemy/on_page_layout/callbacks_runner.rb +1 -0
  234. data/lib/alchemy/page_layout.rb +15 -12
  235. data/lib/alchemy/paths.rb +1 -1
  236. data/lib/alchemy/permissions.rb +7 -6
  237. data/lib/alchemy/resource.rb +25 -15
  238. data/lib/alchemy/resources_helper.rb +12 -18
  239. data/lib/alchemy/routing_constraints.rb +1 -1
  240. data/lib/alchemy/seeder.rb +42 -14
  241. data/lib/alchemy/shell.rb +13 -10
  242. data/lib/alchemy/taggable.rb +1 -0
  243. data/lib/alchemy/tasks/tidy.rb +4 -3
  244. data/lib/alchemy/test_support/config_stubbing.rb +1 -0
  245. data/lib/alchemy/test_support/essence_shared_examples.rb +72 -72
  246. data/lib/alchemy/test_support/factories.rb +1 -1
  247. data/lib/alchemy/test_support/factories/attachment_factory.rb +5 -5
  248. data/lib/alchemy/test_support/factories/content_factory.rb +6 -6
  249. data/lib/alchemy/test_support/factories/dummy_user_factory.rb +7 -7
  250. data/lib/alchemy/test_support/factories/element_factory.rb +9 -9
  251. data/lib/alchemy/test_support/factories/essence_file_factory.rb +3 -3
  252. data/lib/alchemy/test_support/factories/essence_page_factory.rb +3 -3
  253. data/lib/alchemy/test_support/factories/essence_picture_factory.rb +4 -4
  254. data/lib/alchemy/test_support/factories/essence_text_factory.rb +3 -3
  255. data/lib/alchemy/test_support/factories/language_factory.rb +21 -14
  256. data/lib/alchemy/test_support/factories/node_factory.rb +8 -8
  257. data/lib/alchemy/test_support/factories/page_factory.rb +15 -27
  258. data/lib/alchemy/test_support/factories/picture_factory.rb +5 -5
  259. data/lib/alchemy/test_support/factories/site_factory.rb +7 -6
  260. data/lib/alchemy/test_support/integration_helpers.rb +1 -0
  261. data/lib/alchemy/test_support/shared_contexts.rb +5 -4
  262. data/lib/alchemy/test_support/shared_uploader_examples.rb +4 -3
  263. data/lib/alchemy/tinymce.rb +15 -13
  264. data/lib/alchemy/upgrader.rb +8 -7
  265. data/lib/alchemy/upgrader/five_point_zero.rb +41 -0
  266. data/lib/alchemy/upgrader/tasks/element_views_updater.rb +4 -4
  267. data/lib/alchemy/upgrader/tasks/harden_gutentag_migrations.rb +29 -0
  268. data/lib/alchemy/version.rb +1 -1
  269. data/lib/alchemy_cms.rb +52 -50
  270. data/lib/{rails/generators → generators}/alchemy/base.rb +5 -4
  271. data/lib/{rails/generators → generators}/alchemy/elements/elements_generator.rb +13 -9
  272. data/lib/{rails/generators → generators}/alchemy/elements/templates/view.html.erb +0 -0
  273. data/lib/{rails/generators → generators}/alchemy/elements/templates/view.html.haml +0 -0
  274. data/lib/{rails/generators → generators}/alchemy/elements/templates/view.html.slim +0 -0
  275. data/lib/{rails/generators → generators}/alchemy/essence/essence_generator.rb +15 -13
  276. data/lib/generators/alchemy/essence/templates/editor.html.erb +17 -0
  277. data/lib/{rails/generators → generators}/alchemy/essence/templates/view.html.erb +0 -0
  278. data/lib/{rails/generators → generators}/alchemy/install/files/_article.html.erb +0 -0
  279. data/lib/{rails/generators → generators}/alchemy/install/files/_standard.html.erb +0 -0
  280. data/lib/{rails/generators → generators}/alchemy/install/files/alchemy.en.yml +0 -0
  281. data/lib/generators/alchemy/install/files/alchemy_admin.js +1 -0
  282. data/lib/{rails/generators → generators}/alchemy/install/files/all.css +0 -0
  283. data/lib/{rails/generators → generators}/alchemy/install/files/all.js +0 -0
  284. data/lib/{rails/generators → generators}/alchemy/install/files/application.html.erb +0 -0
  285. data/lib/{rails/generators → generators}/alchemy/install/files/article.scss +0 -0
  286. data/lib/generators/alchemy/install/install_generator.rb +169 -0
  287. data/lib/{rails/generators → generators}/alchemy/install/templates/dragonfly.rb.tt +0 -0
  288. data/lib/{rails/generators → generators}/alchemy/install/templates/elements.yml.tt +0 -0
  289. data/lib/{rails/generators → generators}/alchemy/install/templates/menus.yml.tt +0 -0
  290. data/lib/{rails/generators → generators}/alchemy/install/templates/page_layouts.yml.tt +0 -0
  291. data/lib/{rails/generators → generators}/alchemy/menus/menus_generator.rb +2 -2
  292. data/lib/{rails/generators → generators}/alchemy/menus/templates/node.html.erb +1 -4
  293. data/lib/{rails/generators → generators}/alchemy/menus/templates/node.html.haml +1 -4
  294. data/lib/{rails/generators → generators}/alchemy/menus/templates/node.html.slim +1 -4
  295. data/lib/{rails/generators → generators}/alchemy/menus/templates/wrapper.html.erb +1 -1
  296. data/lib/{rails/generators → generators}/alchemy/menus/templates/wrapper.html.haml +1 -1
  297. data/lib/{rails/generators → generators}/alchemy/menus/templates/wrapper.html.slim +1 -1
  298. data/lib/{rails/generators → generators}/alchemy/module/module_generator.rb +3 -2
  299. data/lib/{rails/generators → generators}/alchemy/module/templates/ability.rb.tt +0 -0
  300. data/lib/{rails/generators → generators}/alchemy/module/templates/controller.rb.tt +0 -0
  301. data/lib/{rails/generators → generators}/alchemy/module/templates/module_config.rb.tt +0 -0
  302. data/lib/{rails/generators → generators}/alchemy/page_layouts/page_layouts_generator.rb +5 -4
  303. data/lib/{rails/generators → generators}/alchemy/page_layouts/templates/layout.html.erb +0 -0
  304. data/lib/{rails/generators → generators}/alchemy/page_layouts/templates/layout.html.haml +0 -0
  305. data/lib/{rails/generators → generators}/alchemy/page_layouts/templates/layout.html.slim +0 -0
  306. data/lib/{rails/generators → generators}/alchemy/site_layouts/site_layouts_generator.rb +4 -2
  307. data/lib/{rails/generators → generators}/alchemy/site_layouts/templates/layout.html.erb +0 -0
  308. data/lib/{rails/generators → generators}/alchemy/site_layouts/templates/layout.html.haml +0 -0
  309. data/lib/{rails/generators → generators}/alchemy/site_layouts/templates/layout.html.slim +0 -0
  310. data/lib/{rails/generators → generators}/alchemy/views/views_generator.rb +7 -6
  311. data/lib/kaminari/scoped_pagination_url_helper.rb +1 -0
  312. data/lib/tasks/alchemy/db.rake +3 -19
  313. data/lib/tasks/alchemy/install.rake +5 -48
  314. data/lib/tasks/alchemy/tidy.rake +9 -8
  315. data/lib/tasks/alchemy/upgrade.rake +18 -116
  316. data/package.json +45 -0
  317. data/package/admin.js +14 -0
  318. data/package/src/__tests__/i18n.spec.js +70 -0
  319. data/package/src/i18n.js +48 -0
  320. data/package/src/node_tree.js +72 -0
  321. data/package/src/translations.js +32 -0
  322. data/package/src/utils/__tests__/ajax.spec.js +124 -0
  323. data/package/src/utils/__tests__/events.spec.js +38 -0
  324. data/package/src/utils/ajax.js +48 -0
  325. data/package/src/utils/events.js +16 -0
  326. data/vendor/assets/fonts/fa-regular-400.eot +0 -0
  327. data/vendor/assets/fonts/fa-regular-400.svg +798 -358
  328. data/vendor/assets/fonts/fa-regular-400.ttf +0 -0
  329. data/vendor/assets/fonts/fa-regular-400.woff +0 -0
  330. data/vendor/assets/fonts/fa-regular-400.woff2 +0 -0
  331. data/vendor/assets/fonts/fa-solid-900.eot +0 -0
  332. data/vendor/assets/fonts/fa-solid-900.svg +4933 -1408
  333. data/vendor/assets/fonts/fa-solid-900.ttf +0 -0
  334. data/vendor/assets/fonts/fa-solid-900.woff +0 -0
  335. data/vendor/assets/fonts/fa-solid-900.woff2 +0 -0
  336. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js +1 -2
  337. data/vendor/assets/stylesheets/fontawesome/_core.scss +5 -0
  338. data/vendor/assets/stylesheets/fontawesome/_fixed-width.scss +1 -1
  339. data/vendor/assets/stylesheets/fontawesome/_icons.scss +651 -2
  340. data/vendor/assets/stylesheets/fontawesome/_mixins.scss +0 -1
  341. data/vendor/assets/stylesheets/fontawesome/_rotated-flipped.scss +3 -2
  342. data/vendor/assets/stylesheets/fontawesome/_stacked.scss +1 -1
  343. data/vendor/assets/stylesheets/fontawesome/_variables.scss +662 -9
  344. data/vendor/assets/stylesheets/fontawesome/fontawesome.scss +2 -2
  345. data/vendor/assets/stylesheets/fontawesome/regular.scss +23 -0
  346. data/vendor/assets/stylesheets/fontawesome/solid.scss +24 -0
  347. metadata +112 -88
  348. data/app/assets/javascripts/alchemy/alchemy.i18n.js.coffee +0 -32
  349. data/app/assets/javascripts/alchemy/alchemy.node_tree.js +0 -66
  350. data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +0 -29
  351. data/app/assets/javascripts/alchemy/alchemy.utils.js +0 -45
  352. data/app/helpers/alchemy/essences_helper.rb +0 -119
  353. data/app/models/concerns/alchemy/content_touching.rb +0 -23
  354. data/app/serializers/alchemy/legacy_element_serializer.rb +0 -15
  355. data/app/views/alchemy/admin/contents/_missing.html.erb +0 -17
  356. data/app/views/alchemy/admin/pages/_menu_fields.html.erb +0 -37
  357. data/app/views/alchemy/admin/pages/configure_external.html.erb +0 -32
  358. data/app/views/alchemy/elements/_editor_not_found.html.erb +0 -4
  359. data/app/views/alchemy/navigation/_image_link.html.erb +0 -14
  360. data/app/views/alchemy/navigation/_link.html.erb +0 -19
  361. data/app/views/alchemy/navigation/_renderer.html.erb +0 -29
  362. data/db/migrate/20180226123013_alchemy_four_point_zero.rb +0 -363
  363. data/db/migrate/20180227224537_migrate_tags_to_gutentag.rb +0 -41
  364. data/db/migrate/20180519204655_add_fixed_to_alchemy_elements.rb +0 -6
  365. data/db/migrate/20191016073858_create_alchemy_essence_pages.rb +0 -8
  366. data/db/migrate/20191029212236_create_alchemy_nodes.rb +0 -24
  367. data/db/migrate/20200226081535_add_site_id_to_alchemy_nodes.rb +0 -15
  368. data/lib/alchemy/ssl_protection.rb +0 -34
  369. data/lib/alchemy/tasks/helpers.rb +0 -81
  370. data/lib/alchemy/test_support/controller_requests.rb +0 -93
  371. data/lib/alchemy/upgrader/four_point_four.rb +0 -52
  372. data/lib/alchemy/upgrader/four_point_one.rb +0 -42
  373. data/lib/alchemy/upgrader/four_point_six.rb +0 -50
  374. data/lib/alchemy/upgrader/four_point_two.rb +0 -85
  375. data/lib/alchemy/upgrader/tasks/cells_migration.rb +0 -43
  376. data/lib/alchemy/upgrader/tasks/cells_upgrader.rb +0 -148
  377. data/lib/alchemy/upgrader/tasks/element_partial_name_variable_updater.rb +0 -28
  378. data/lib/alchemy/upgrader/tasks/harden_acts_as_taggable_on_migrations.rb +0 -27
  379. data/lib/alchemy/upgrader/tasks/picture_gallery_migration.rb +0 -65
  380. data/lib/alchemy/upgrader/tasks/picture_gallery_upgrader.rb +0 -210
  381. data/lib/rails/generators/alchemy/essence/templates/editor.html.erb +0 -15
  382. data/lib/rails/generators/alchemy/install/install_generator.rb +0 -60
  383. data/lib/tasks/alchemy/convert.rake +0 -97
  384. data/vendor/assets/javascripts/sortable/Sortable.min.js +0 -2
  385. data/vendor/assets/stylesheets/fontawesome/fa-regular.scss +0 -22
  386. data/vendor/assets/stylesheets/fontawesome/fa-solid.scss +0 -23
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddLanguageIdForeignKeyToAlchemyPages < ActiveRecord::Migration[5.2]
4
+ def change
5
+ add_foreign_key :alchemy_pages, :alchemy_languages, column: :language_id
6
+ change_column_null :alchemy_pages, :language_id, false, Alchemy::Language.default&.id
7
+ end
8
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+ class AddMenuTypeToAlchemyNodes < ActiveRecord::Migration[5.2]
3
+ class LocalNode < ActiveRecord::Base
4
+ self.table_name = :alchemy_nodes
5
+ acts_as_nested_set scope: :language_id
6
+
7
+ def self.root_for(node)
8
+ return node if node.parent_id.nil?
9
+
10
+ root_for(node.parent)
11
+ end
12
+ end
13
+
14
+ def up
15
+ add_column :alchemy_nodes, :menu_type, :string
16
+ LocalNode.all.each do |node|
17
+ root = LocalNode.root_for(node)
18
+ menu_type = root.name.parameterize.underscore
19
+ node.update(menu_type: menu_type)
20
+ end
21
+ change_column_null :alchemy_nodes, :menu_type, false
22
+ end
23
+
24
+ def down
25
+ remove_column :alchemy_nodes, :menu_type
26
+ end
27
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+ class MakePageLayoutpageNullFalse < ActiveRecord::Migration[5.2]
3
+ def change
4
+ change_column_null :alchemy_pages, :layoutpage, false, false
5
+ end
6
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+ class RemoveVisibleFromAlchemyPages < ActiveRecord::Migration[5.2]
3
+ class LocalPage < ActiveRecord::Base
4
+ self.table_name = "alchemy_pages"
5
+
6
+ scope :invisible, -> { where(visible: [false, nil]) }
7
+ scope :contentpages, -> { where(layoutpage: [false, nil]) }
8
+ end
9
+
10
+ def up
11
+ if LocalPage.invisible.contentpages.where.not(parent_id: nil).any?
12
+ abort "You have invisible pages in your database! " \
13
+ "Please re-structure your page tree before running this migration. " \
14
+ "You might also downgrade to Alchemy 4.6 and " \
15
+ "run the `alchemy:upgrade:4.6:restructure_page_tree` rake task."
16
+ end
17
+
18
+ remove_column :alchemy_pages, :visible
19
+ end
20
+
21
+ def down
22
+ add_column :alchemy_pages, :visible, :boolean, default: false
23
+ end
24
+ end
@@ -47,6 +47,7 @@ module Alchemy
47
47
  # Try to get the locale from user settings.
48
48
  def locale_from_user
49
49
  return if !current_alchemy_user
50
+
50
51
  if user_has_preferred_language?
51
52
  current_alchemy_user.language
52
53
  end
@@ -55,6 +56,7 @@ module Alchemy
55
56
  # Checks if the +current_alchemy_user+ has a preferred language set or not.
56
57
  def user_has_preferred_language?
57
58
  return if !current_alchemy_user
59
+
58
60
  current_alchemy_user.respond_to?(:language) &&
59
61
  current_alchemy_user.language.present? &&
60
62
  current_alchemy_user.language.respond_to?(:to_sym)
@@ -62,7 +64,7 @@ module Alchemy
62
64
 
63
65
  # Try to get the locale from browser headers.
64
66
  def locale_from_browser
65
- request.env['HTTP_ACCEPT_LANGUAGE'].try(:scan, /\A[a-z]{2}/).try(:first)
67
+ request.env["HTTP_ACCEPT_LANGUAGE"].try(:scan, /\A[a-z]{2}/).try(:first)
66
68
  end
67
69
  end
68
70
  end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "uri"
4
+
5
+ module Alchemy
6
+ module Admin
7
+ # = Preview window URL configuration
8
+ #
9
+ # By default Alchemy uses its internal page preview renderer,
10
+ # but you can configure it to be any URL instead.
11
+ #
12
+ # Basic Auth is supported.
13
+ #
14
+ # == Example config/alchemy/config.yml
15
+ #
16
+ # preview:
17
+ # host: https://www.my-static-site.com
18
+ # auth:
19
+ # username: <%= ENV["BASIC_AUTH_USERNAME"] %>
20
+ # password: <%= ENV["BASIC_AUTH_PASSWORD"] %>
21
+ #
22
+ # Preview config per site is supported as well.
23
+ #
24
+ # == Example config/alchemy/config.yml
25
+ #
26
+ # preview:
27
+ # My site name:
28
+ # host: https://www.my-static-site.com
29
+ # auth:
30
+ # username: <%= ENV["BASIC_AUTH_USERNAME"] %>
31
+ # password: <%= ENV["BASIC_AUTH_PASSWORD"] %>
32
+ #
33
+ class PreviewUrl
34
+ class MissingProtocolError < StandardError; end
35
+
36
+ def initialize(routes:)
37
+ @routes = routes.url_helpers
38
+ end
39
+
40
+ def url_for(page)
41
+ @preview_config = preview_config_for(page)
42
+
43
+ if @preview_config && uri
44
+ uri_class.build(
45
+ host: uri.host,
46
+ path: page.url_path,
47
+ userinfo: userinfo,
48
+ ).to_s
49
+ else
50
+ routes.admin_page_path(page)
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ attr_reader :routes
57
+
58
+ def preview_config_for(page)
59
+ preview_config = Alchemy::Config.get(:preview)
60
+ return unless preview_config
61
+
62
+ preview_config[page.site.name] || preview_config
63
+ end
64
+
65
+ def uri
66
+ return unless @preview_config["host"]
67
+
68
+ URI(@preview_config["host"])
69
+ end
70
+
71
+ def uri_class
72
+ if uri.class == URI::Generic
73
+ raise MissingProtocolError, "Please provide the protocol with preview['host']"
74
+ else
75
+ uri.class
76
+ end
77
+ end
78
+
79
+ def userinfo
80
+ auth = @preview_config["auth"]
81
+ auth ? "#{auth["username"]}:#{auth["password"]}" : nil
82
+ end
83
+ end
84
+ end
85
+ end
@@ -53,13 +53,13 @@ module Alchemy
53
53
 
54
54
  # Defaults
55
55
  #
56
- @@user_class_name = 'User'
56
+ @@user_class_name = "User"
57
57
  @@user_class_primary_key = :id
58
- @@current_user_method = 'current_user'
59
- @@signup_path = '/signup'
60
- @@login_path = '/login'
61
- @@logout_path = '/logout'
62
- @@logout_method = 'delete'
58
+ @@current_user_method = "current_user"
59
+ @@signup_path = "/signup"
60
+ @@login_path = "/login"
61
+ @@logout_path = "/logout"
62
+ @@logout_method = "delete"
63
63
 
64
64
  # Returns the user class
65
65
  #
@@ -76,8 +76,9 @@ module Alchemy
76
76
  # Prefix with :: when getting to avoid constant name conflicts
77
77
  def self.user_class_name
78
78
  if !@@user_class_name.is_a?(String)
79
- raise TypeError, 'Alchemy.user_class_name must be a String, not a Class.'
79
+ raise TypeError, "Alchemy.user_class_name must be a String, not a Class."
80
80
  end
81
+
81
82
  "::#{@@user_class_name}"
82
83
  end
83
84
 
@@ -14,10 +14,10 @@ module Alchemy
14
14
  def dependencies
15
15
  case @name.to_s
16
16
  when /^alchemy\/pages\/show/
17
- PageLayout.all.map { |p| "alchemy/page_layouts/_#{p['name']}" }
17
+ PageLayout.all.map { |p| "alchemy/page_layouts/_#{p["name"]}" }
18
18
  when /^alchemy\/page_layouts\/_(\w+)/
19
19
  page_layout = PageLayout.get($1)
20
- layout_elements = page_layout.fetch('elements', [])
20
+ layout_elements = page_layout.fetch("elements", [])
21
21
  layout_elements.map { |name| "alchemy/elements/_#{name}_view" } +
22
22
  layout_elements.map { |name| "alchemy/elements/_#{name}" }
23
23
  when /^alchemy\/elements\/_(\w+)_view/, /^alchemy\/elements\/_(\w+)/
@@ -32,9 +32,10 @@ module Alchemy
32
32
  private
33
33
 
34
34
  def essence_types(name)
35
- element = Element.definitions.detect { |e| e['name'] == name }
35
+ element = Element.definitions.detect { |e| e["name"] == name }
36
36
  return [] unless element
37
- element.fetch('contents', []).collect { |c| c['type'] }
37
+
38
+ element.fetch("contents", []).collect { |c| c["type"] }
38
39
  end
39
40
  end
40
41
  end
@@ -32,9 +32,7 @@ module Alchemy
32
32
  # any not nil value is the new default
33
33
  def deprecated_configs
34
34
  {
35
- url_nesting: true,
36
- require_ssl: nil,
37
- auto_logout_time: nil,
35
+ redirect_to_public_child: nil,
38
36
  }
39
37
  end
40
38
 
@@ -78,11 +76,11 @@ module Alchemy
78
76
  if deprecated_configs.key?(name.to_sym)
79
77
  config = deprecated_configs[name.to_sym]
80
78
  if config.nil?
81
- Alchemy::Deprecation.warn("#{name} configuration is deprecated and will be removed from Alchemy 5.0")
79
+ Alchemy::Deprecation.warn("#{name} configuration is deprecated and will be removed from Alchemy 5.1")
82
80
  else
83
81
  value = show[name.to_s]
84
82
  if value != config
85
- Alchemy::Deprecation.warn("Setting #{name} configuration to #{value} is deprecated and will be always #{config} in Alchemy 5.0")
83
+ Alchemy::Deprecation.warn("Setting #{name} configuration to #{value} is deprecated and will be always #{config} in Alchemy 5.1")
86
84
  end
87
85
  end
88
86
  end
@@ -28,7 +28,9 @@ module Alchemy
28
28
  # matches the current I18n.locale then the prefix os omitted.
29
29
  # Also, if only one published language exists.
30
30
  #
31
- def prefix_locale?(locale = Language.current.code)
31
+ def prefix_locale?(locale = Language.current&.code)
32
+ return false unless locale
33
+
32
34
  multi_language? && locale != ::I18n.default_locale.to_s
33
35
  end
34
36
 
@@ -8,7 +8,7 @@ module Alchemy
8
8
  before_action :set_current_alchemy_site
9
9
  before_action :set_alchemy_language
10
10
 
11
- helper 'alchemy/pages'
11
+ helper "alchemy/pages"
12
12
 
13
13
  helper_method :current_alchemy_user,
14
14
  :alchemy_user_signed_in?,
@@ -36,6 +36,7 @@ module Alchemy
36
36
  def current_alchemy_user
37
37
  current_user_method = Alchemy.current_user_method
38
38
  raise NoCurrentUserFoundError if !respond_to?(current_user_method, true)
39
+
39
40
  send current_user_method
40
41
  end
41
42
 
@@ -66,8 +67,8 @@ module Alchemy
66
67
  else
67
68
  # find the best language and remember it for later
68
69
  @language = load_alchemy_language_from_params ||
69
- load_alchemy_language_from_session ||
70
- Language.default
70
+ load_alchemy_language_from_session ||
71
+ Language.default
71
72
  end
72
73
  store_current_alchemy_language(@language)
73
74
  end
@@ -81,7 +82,7 @@ module Alchemy
81
82
  # Load language from session if it's present on current site.
82
83
  # Otherwise return nil so we can load the default language from current site.
83
84
  def load_alchemy_language_from_session
84
- if session[:alchemy_language_id].present?
85
+ if session[:alchemy_language_id].present? && Site.current
85
86
  Site.current.languages.find_by(id: session[:alchemy_language_id])
86
87
  end
87
88
  end
@@ -96,7 +97,7 @@ module Alchemy
96
97
  # Also stores language in +Language.current+
97
98
  #
98
99
  def store_current_alchemy_language(language)
99
- if language && language.id
100
+ if language&.id
100
101
  session[:alchemy_language_id] = language.id
101
102
  Language.current = language
102
103
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Alchemy
2
- Deprecation = ActiveSupport::Deprecation.new('5.0', 'Alchemy')
3
+ Deprecation = ActiveSupport::Deprecation.new("5.1", "Alchemy")
3
4
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'alchemy/logger'
3
+ require "alchemy/logger"
4
4
 
5
5
  module Alchemy
6
6
  # Loads elements from given page
@@ -86,7 +86,7 @@ module Alchemy
86
86
  Alchemy::Page.find_by(
87
87
  language: Alchemy::Language.current,
88
88
  page_layout: page_or_layout,
89
- restricted: false
89
+ restricted: false,
90
90
  )
91
91
  end
92
92
  end
@@ -104,10 +104,10 @@ module Alchemy
104
104
 
105
105
  def random_function
106
106
  case ActiveRecord::Base.connection_config[:adapter]
107
- when 'postgresql', 'sqlite3'
108
- then 'RANDOM()'
107
+ when "postgresql", "sqlite3"
108
+ "RANDOM()"
109
109
  else
110
- 'RAND()'
110
+ "RAND()"
111
111
  end
112
112
  end
113
113
  end
@@ -1,32 +1,47 @@
1
+ # frozen_string_literal: true
1
2
  module Alchemy
2
3
  class Engine < Rails::Engine
3
4
  isolate_namespace Alchemy
4
- engine_name 'alchemy'
5
- config.mount_at = '/'
5
+ engine_name "alchemy"
6
+ config.mount_at = "/"
6
7
 
7
- initializer 'alchemy.lookup_context' do
8
- Alchemy::LOOKUP_CONTEXT = ActionView::LookupContext.new(Rails.root.join('app', 'views', 'alchemy'))
8
+ initializer "alchemy.lookup_context" do
9
+ Alchemy::LOOKUP_CONTEXT = ActionView::LookupContext.new(Rails.root.join("app", "views", "alchemy"))
9
10
  end
10
11
 
11
- initializer 'alchemy.dependency_tracker' do
12
+ initializer "alchemy.admin.preview_url" do
13
+ Alchemy::Admin::PREVIEW_URL = Alchemy::Admin::PreviewUrl.new(routes: Alchemy::Engine.routes)
14
+ end
15
+
16
+ initializer "alchemy.dependency_tracker" do
12
17
  [:erb, :slim, :haml].each do |handler|
13
18
  ActionView::DependencyTracker.register_tracker(handler, CacheDigests::TemplateTracker)
14
19
  end
15
20
  end
16
21
 
17
- initializer 'alchemy.non_digest_assets' do
22
+ initializer "alchemy.non_digest_assets" do
18
23
  NonStupidDigestAssets.whitelist += [/^tinymce\//]
19
24
  end
20
25
 
21
26
  # Gutentag downcases all tgas before save.
22
27
  # We support having tags with uppercase characters.
23
28
  # The Gutentag search is case insensitive.
24
- initializer 'alchemy.gutentag_normalizer' do
29
+ initializer "alchemy.gutentag_normalizer" do
25
30
  Gutentag.normaliser = ->(value) { value.to_s }
26
31
  end
27
32
 
33
+ # Custom Ransack sort arrows
34
+ initializer "alchemy.ransack" do
35
+ Ransack.configure do |config|
36
+ config.custom_arrows = {
37
+ up_arrow: '<i class="fa fas fa-xs fa-arrow-up"></i>',
38
+ down_arrow: '<i class="fa fas fa-xs fa-arrow-down"></i>',
39
+ }
40
+ end
41
+ end
42
+
28
43
  config.after_initialize do
29
- require_relative './userstamp'
44
+ require_relative "./userstamp"
30
45
  end
31
46
  end
32
47
  end
@@ -23,13 +23,6 @@ module Alchemy
23
23
  end
24
24
  end
25
25
 
26
- class DefaultLanguageNotDeletable < StandardError
27
- # Raised if one tries to delete the default language.
28
- def message
29
- "Default language is not deletable!"
30
- end
31
- end
32
-
33
26
  class ElementDefinitionError < StandardError
34
27
  # Raised if element definition can not be found.
35
28
  def initialize(attributes)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_record'
3
+ require "active_record"
4
4
 
5
5
  module Alchemy #:nodoc:
6
6
  # A bogus association that skips eager loading for essences not having an ingredient association
@@ -40,7 +40,7 @@ module Alchemy #:nodoc:
40
40
  register_as_essence_association!
41
41
 
42
42
  configuration = {
43
- ingredient_column: 'body'
43
+ ingredient_column: "body",
44
44
  }.update(options)
45
45
 
46
46
  @_classes_with_ingredient_association ||= []
@@ -48,7 +48,7 @@ module Alchemy #:nodoc:
48
48
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
49
49
  attr_writer :validation_errors
50
50
  include Alchemy::Essence::InstanceMethods
51
- stampable stamper_class_name: Alchemy.user_class_name
51
+
52
52
  validate :validate_ingredient, on: :update, if: -> { validations.any? }
53
53
 
54
54
  has_one :content, as: :essence, class_name: "Alchemy::Content", inverse_of: :essence
@@ -62,7 +62,7 @@ module Alchemy #:nodoc:
62
62
  delegate :trashed?, to: :element, allow_nil: true
63
63
  delegate :public?, to: :element, allow_nil: true
64
64
 
65
- after_update :touch_content
65
+ after_save :touch_element
66
66
 
67
67
  def acts_as_essence_class
68
68
  #{name}
@@ -109,7 +109,7 @@ module Alchemy #:nodoc:
109
109
  def register_as_essence_association!
110
110
  klass_name = model_name.to_s
111
111
  arguments = [:has_many, klass_name.demodulize.tableize.to_sym, through: :contents,
112
- source: :essence, source_type: klass_name]
112
+ source: :essence, source_type: klass_name]
113
113
  %w(Page Element).each { |k| "Alchemy::#{k}".constantize.send(*arguments) }
114
114
  end
115
115
  end
@@ -171,7 +171,7 @@ module Alchemy #:nodoc:
171
171
  end
172
172
 
173
173
  def validations
174
- @validations ||= definition.present? ? definition['validate'] || [] : []
174
+ @validations ||= definition.present? ? definition["validate"] || [] : []
175
175
  end
176
176
 
177
177
  def validation_errors
@@ -187,6 +187,7 @@ module Alchemy #:nodoc:
187
187
 
188
188
  def validate_uniqueness(validate = true)
189
189
  return if !validate || !public?
190
+
190
191
  if duplicates.any?
191
192
  errors.add(ingredient_column, :taken)
192
193
  validation_errors << :taken
@@ -194,7 +195,7 @@ module Alchemy #:nodoc:
194
195
  end
195
196
 
196
197
  def validate_format(format)
197
- matcher = Config.get('format_matchers')[format] || format
198
+ matcher = Config.get("format_matchers")[format] || format
198
199
  if ingredient.to_s.match(Regexp.new(matcher)).nil?
199
200
  errors.add(ingredient_column, :invalid)
200
201
  validation_errors << :invalid
@@ -216,7 +217,7 @@ module Alchemy #:nodoc:
216
217
  end
217
218
  end
218
219
 
219
- # Returns the value stored from the database column that is configured as ingredient column.
220
+ # Sets the value stored in the database column that is configured as ingredient column.
220
221
  def ingredient=(value)
221
222
  if respond_to?(ingredient_setter_method)
222
223
  send(ingredient_setter_method, value)
@@ -225,19 +226,19 @@ module Alchemy #:nodoc:
225
226
 
226
227
  # Returns the setter method for ingredient column
227
228
  def ingredient_setter_method
228
- ingredient_column.to_s + '='
229
+ ingredient_column.to_s + "="
229
230
  end
230
231
 
231
232
  # Essence definition from config/elements.yml
232
233
  def definition
233
234
  return {} if element.nil? || element.content_definitions.nil?
234
- element.content_definitions.detect { |c| c['name'] == content.name } || {}
235
+
236
+ element.content_definitions.detect { |c| c["name"] == content.name } || {}
235
237
  end
236
238
 
237
- # Touch content. Called after update.
238
- def touch_content
239
- return nil if content.nil?
240
- content.touch
239
+ # Touches element. Called after save.
240
+ def touch_element
241
+ element&.touch
241
242
  end
242
243
 
243
244
  # Returns the first x (default 30) characters of ingredient for the Element#preview_text method.
@@ -247,11 +248,11 @@ module Alchemy #:nodoc:
247
248
  end
248
249
 
249
250
  def open_link_in_new_window?
250
- respond_to?(:link_target) && link_target == 'blank'
251
+ respond_to?(:link_target) && link_target == "blank"
251
252
  end
252
253
 
253
254
  def partial_name
254
- self.class.name.split('::').last.underscore
255
+ self.class.name.split("::").last.underscore
255
256
  end
256
257
 
257
258
  def acts_as_essence?