alchemy_cms 6.1.10 → 7.0.0.pre.a
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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +0 -3
- data/.gitignore +1 -6
- data/CHANGELOG.md +19 -44
- data/Gemfile +1 -1
- data/Rakefile +14 -9
- data/alchemy_cms.gemspec +2 -3
- data/app/assets/javascripts/alchemy/alchemy.dirty.js.coffee +1 -1
- data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +18 -32
- data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +2 -2
- data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +2 -2
- data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +27 -29
- data/app/assets/stylesheets/alchemy/elements.scss +16 -35
- data/app/assets/stylesheets/alchemy/forms.scss +0 -4
- data/app/assets/stylesheets/alchemy/node-select.scss +2 -2
- data/app/controllers/alchemy/admin/attachments_controller.rb +0 -1
- data/app/controllers/alchemy/admin/elements_controller.rb +7 -32
- data/app/controllers/alchemy/admin/pages_controller.rb +1 -1
- data/app/controllers/alchemy/admin/pictures_controller.rb +1 -1
- data/app/controllers/alchemy/admin/resources_controller.rb +1 -18
- data/app/controllers/alchemy/api/elements_controller.rb +0 -2
- data/app/controllers/alchemy/api/pages_controller.rb +8 -4
- data/app/controllers/alchemy/messages_controller.rb +9 -9
- data/app/controllers/alchemy/pages_controller.rb +23 -18
- data/app/decorators/alchemy/element_editor.rb +10 -30
- data/app/helpers/alchemy/admin/elements_helper.rb +0 -2
- data/app/helpers/alchemy/elements_block_helper.rb +5 -42
- data/app/helpers/alchemy/elements_helper.rb +3 -11
- data/app/helpers/alchemy/pages_helper.rb +0 -4
- data/app/models/alchemy/attachment.rb +6 -3
- data/app/models/alchemy/base_record.rb +2 -0
- data/app/models/alchemy/eager_loading.rb +0 -1
- data/app/models/alchemy/element/element_ingredients.rb +1 -8
- data/app/models/alchemy/element/presenters.rb +9 -25
- data/app/models/alchemy/element.rb +2 -18
- data/app/models/alchemy/ingredient.rb +17 -6
- data/app/models/alchemy/ingredients/audio.rb +2 -0
- data/app/models/alchemy/ingredients/datetime.rb +3 -1
- data/app/models/alchemy/ingredients/file.rb +7 -0
- data/app/models/alchemy/ingredients/headline.rb +6 -0
- data/app/models/alchemy/ingredients/link.rb +2 -0
- data/app/models/alchemy/ingredients/node.rb +2 -0
- data/app/models/alchemy/ingredients/page.rb +2 -0
- data/app/models/alchemy/ingredients/picture.rb +11 -0
- data/app/models/alchemy/ingredients/richtext.rb +6 -0
- data/app/models/alchemy/ingredients/select.rb +1 -0
- data/app/models/alchemy/ingredients/text.rb +8 -0
- data/app/models/alchemy/ingredients/video.rb +2 -0
- data/app/models/alchemy/node.rb +9 -6
- data/app/models/alchemy/page/page_elements.rb +5 -26
- data/app/models/alchemy/page/page_layouts.rb +0 -14
- data/app/models/alchemy/page/page_natures.rb +0 -10
- data/app/models/alchemy/page.rb +0 -10
- data/app/models/alchemy/picture/transformations.rb +0 -30
- data/app/models/alchemy/picture/url.rb +1 -1
- data/app/models/alchemy/picture.rb +14 -13
- data/app/models/alchemy/picture_thumb/create.rb +7 -18
- data/app/models/alchemy/picture_thumb/file_store.rb +33 -0
- data/app/models/alchemy/picture_thumb.rb +10 -10
- data/app/models/concerns/alchemy/picture_thumbnails.rb +2 -6
- data/app/serializers/alchemy/element_serializer.rb +1 -6
- data/app/services/alchemy/delete_elements.rb +1 -7
- data/app/services/alchemy/duplicate_element.rb +1 -6
- data/app/views/alchemy/admin/elements/_element.html.erb +5 -22
- data/app/views/alchemy/admin/elements/create.js.erb +1 -1
- data/app/views/alchemy/admin/elements/fold.js.erb +2 -2
- data/app/views/alchemy/admin/elements/order.js.erb +1 -1
- data/app/views/alchemy/admin/elements/update.js.erb +1 -2
- data/app/views/alchemy/admin/pages/_external_link.html.erb +2 -2
- data/app/views/alchemy/admin/pages/_file_link.html.erb +2 -2
- data/app/views/alchemy/admin/pages/_internal_link.html.erb +2 -2
- data/app/views/alchemy/admin/pages/_table.html.erb +0 -6
- data/app/views/alchemy/admin/pages/_tinymce_custom_config.html.erb +3 -6
- data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
- data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +1 -3
- data/app/views/alchemy/admin/pictures/_infos.html.erb +4 -6
- data/app/views/alchemy/admin/resources/_per_page_select.html.erb +1 -1
- data/app/views/alchemy/ingredients/_boolean_editor.html.erb +1 -1
- data/app/views/alchemy/ingredients/_headline_editor.html.erb +1 -1
- data/app/views/alchemy/ingredients/_html_editor.html.erb +1 -1
- data/app/views/alchemy/ingredients/_node_editor.html.erb +1 -1
- data/app/views/alchemy/ingredients/_picture_editor.html.erb +4 -4
- data/app/views/alchemy/ingredients/_select_editor.html.erb +2 -2
- data/app/views/alchemy/ingredients/_text_editor.html.erb +1 -1
- data/app/views/alchemy/ingredients/shared/_link_tools.html.erb +3 -3
- data/app/views/alchemy/pages/_meta_data.html.erb +0 -1
- data/app/views/layouts/alchemy/admin.html.erb +5 -1
- data/config/alchemy/config.yml +6 -6
- data/config/brakeman.ignore +56 -57
- data/config/locales/alchemy.en.yml +99 -113
- data/config/routes.rb +1 -16
- data/db/migrate/20230121212637_alchemy_six_point_one.rb +248 -0
- data/lib/alchemy/cache_digests/template_tracker.rb +6 -7
- data/lib/alchemy/config.rb +2 -2
- data/lib/alchemy/deprecation.rb +1 -1
- data/lib/alchemy/errors.rb +0 -11
- data/lib/alchemy/hints.rb +10 -10
- data/lib/alchemy/permissions.rb +4 -17
- data/lib/alchemy/routing_constraints.rb +3 -3
- data/lib/alchemy/searchable_resource.rb +38 -0
- data/lib/alchemy/seeder.rb +2 -8
- data/lib/alchemy/tasks/tidy.rb +0 -38
- data/lib/alchemy/test_support/capybara_helpers.rb +69 -0
- data/lib/alchemy/test_support/factories/element_factory.rb +0 -6
- data/lib/alchemy/test_support/factories/ingredient_factory.rb +1 -1
- data/lib/alchemy/test_support/factories/page_factory.rb +4 -2
- data/lib/alchemy/test_support/having_picture_thumbnails_examples.rb +0 -20
- data/lib/alchemy/test_support/shared_dom_ids_examples.rb +1 -1
- data/lib/alchemy/test_support/shared_ingredient_examples.rb +1 -1
- data/lib/alchemy/tinymce.rb +1 -18
- data/lib/alchemy/upgrader/seven_point_zero.rb +45 -0
- data/lib/alchemy/upgrader/tasks/.keep +0 -0
- data/lib/alchemy/upgrader.rb +8 -3
- data/lib/alchemy/version.rb +1 -1
- data/lib/alchemy.rb +0 -19
- data/lib/alchemy_cms.rb +1 -2
- data/lib/generators/alchemy/elements/elements_generator.rb +0 -1
- data/lib/generators/alchemy/elements/templates/view.html.erb +1 -10
- data/lib/generators/alchemy/elements/templates/view.html.haml +1 -9
- data/lib/generators/alchemy/elements/templates/view.html.slim +1 -9
- data/lib/generators/alchemy/install/files/alchemy.en.yml +7 -8
- data/lib/generators/alchemy/install/files/application.html.erb +1 -1
- data/lib/generators/alchemy/install/install_generator.rb +18 -34
- data/lib/generators/alchemy/install/templates/elements.yml.tt +12 -12
- data/lib/non_stupid_digest_assets.rb +1 -1
- data/lib/tasks/alchemy/thumbnails.rake +2 -21
- data/lib/tasks/alchemy/tidy.rake +1 -12
- data/lib/tasks/alchemy/upgrade.rake +10 -47
- data/package/dist/admin.js +16 -0
- data/package/dist/admin.js.map +7 -0
- data/package.json +5 -3
- metadata +18 -147
- data/app/controllers/alchemy/admin/contents_controller.rb +0 -21
- data/app/controllers/alchemy/admin/essence_audios_controller.rb +0 -30
- data/app/controllers/alchemy/admin/essence_files_controller.rb +0 -31
- data/app/controllers/alchemy/admin/essence_pictures_controller.rb +0 -43
- data/app/controllers/alchemy/admin/essence_videos_controller.rb +0 -34
- data/app/controllers/alchemy/api/contents_controller.rb +0 -52
- data/app/decorators/alchemy/content_editor.rb +0 -119
- data/app/helpers/alchemy/admin/contents_helper.rb +0 -42
- data/app/helpers/alchemy/admin/essences_helper.rb +0 -31
- data/app/models/alchemy/content/factory.rb +0 -143
- data/app/models/alchemy/content.rb +0 -247
- data/app/models/alchemy/element/element_contents.rb +0 -200
- data/app/models/alchemy/element/element_essences.rb +0 -133
- data/app/models/alchemy/essence_audio.rb +0 -13
- data/app/models/alchemy/essence_boolean.rb +0 -20
- data/app/models/alchemy/essence_date.rb +0 -25
- data/app/models/alchemy/essence_file.rb +0 -49
- data/app/models/alchemy/essence_headline.rb +0 -41
- data/app/models/alchemy/essence_html.rb +0 -23
- data/app/models/alchemy/essence_link.rb +0 -21
- data/app/models/alchemy/essence_node.rb +0 -19
- data/app/models/alchemy/essence_page.rb +0 -17
- data/app/models/alchemy/essence_picture.rb +0 -67
- data/app/models/alchemy/essence_picture_view.rb +0 -90
- data/app/models/alchemy/essence_richtext.rb +0 -44
- data/app/models/alchemy/essence_select.rb +0 -19
- data/app/models/alchemy/essence_text.rb +0 -23
- data/app/models/alchemy/essence_video.rb +0 -13
- data/app/serializers/alchemy/content_serializer.rb +0 -17
- data/app/serializers/alchemy/essence_boolean_serializer.rb +0 -10
- data/app/serializers/alchemy/essence_date_serializer.rb +0 -10
- data/app/serializers/alchemy/essence_file_serializer.rb +0 -13
- data/app/serializers/alchemy/essence_html_serializer.rb +0 -10
- data/app/serializers/alchemy/essence_link_serializer.rb +0 -13
- data/app/serializers/alchemy/essence_picture_serializer.rb +0 -28
- data/app/serializers/alchemy/essence_richtext_serializer.rb +0 -11
- data/app/serializers/alchemy/essence_select_serializer.rb +0 -10
- data/app/serializers/alchemy/essence_text_serializer.rb +0 -22
- data/app/views/alchemy/admin/contents/create.js.erb +0 -21
- data/app/views/alchemy/admin/essence_audios/edit.html.erb +0 -7
- data/app/views/alchemy/admin/essence_files/edit.html.erb +0 -21
- data/app/views/alchemy/admin/essence_pictures/destroy.js.erb +0 -5
- data/app/views/alchemy/admin/essence_pictures/edit.html.erb +0 -30
- data/app/views/alchemy/admin/essence_pictures/save_link.js.erb +0 -3
- data/app/views/alchemy/admin/essence_pictures/update.js.erb +0 -8
- data/app/views/alchemy/admin/essence_videos/edit.html.erb +0 -12
- data/app/views/alchemy/essences/_essence_audio_editor.html.erb +0 -4
- data/app/views/alchemy/essences/_essence_audio_view.html.erb +0 -15
- data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +0 -11
- data/app/views/alchemy/essences/_essence_boolean_view.html.erb +0 -2
- data/app/views/alchemy/essences/_essence_date_editor.html.erb +0 -16
- data/app/views/alchemy/essences/_essence_date_view.html.erb +0 -10
- data/app/views/alchemy/essences/_essence_file_editor.html.erb +0 -54
- data/app/views/alchemy/essences/_essence_file_view.html.erb +0 -18
- data/app/views/alchemy/essences/_essence_headline_editor.html.erb +0 -36
- data/app/views/alchemy/essences/_essence_headline_view.html.erb +0 -10
- data/app/views/alchemy/essences/_essence_html_editor.html.erb +0 -10
- data/app/views/alchemy/essences/_essence_html_view.html.erb +0 -2
- data/app/views/alchemy/essences/_essence_link_editor.html.erb +0 -30
- data/app/views/alchemy/essences/_essence_link_view.html.erb +0 -10
- data/app/views/alchemy/essences/_essence_node_editor.html.erb +0 -27
- data/app/views/alchemy/essences/_essence_node_view.html.erb +0 -1
- data/app/views/alchemy/essences/_essence_page_editor.html.erb +0 -26
- data/app/views/alchemy/essences/_essence_page_view.html.erb +0 -5
- data/app/views/alchemy/essences/_essence_picture_editor.html.erb +0 -59
- data/app/views/alchemy/essences/_essence_picture_view.html.erb +0 -6
- data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +0 -14
- data/app/views/alchemy/essences/_essence_richtext_view.html.erb +0 -4
- data/app/views/alchemy/essences/_essence_select_editor.html.erb +0 -28
- data/app/views/alchemy/essences/_essence_select_view.html.erb +0 -2
- data/app/views/alchemy/essences/_essence_text_editor.html.erb +0 -29
- data/app/views/alchemy/essences/_essence_text_view.html.erb +0 -17
- data/app/views/alchemy/essences/_essence_video_editor.html.erb +0 -4
- data/app/views/alchemy/essences/_essence_video_view.html.erb +0 -19
- data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +0 -59
- data/app/views/alchemy/essences/shared/_linkable_essence_tools.html.erb +0 -20
- data/app/views/alchemy/pages/show.rss.builder +0 -21
- data/db/migrate/20200226213334_alchemy_four_point_four.rb +0 -313
- data/db/migrate/20200423073425_create_alchemy_essence_nodes.rb +0 -11
- data/db/migrate/20200504210159_remove_site_id_from_nodes.rb +0 -28
- data/db/migrate/20200505215518_add_language_id_foreign_key_to_alchemy_pages.rb +0 -8
- data/db/migrate/20200511113603_add_menu_type_to_alchemy_nodes.rb +0 -27
- data/db/migrate/20200514091507_make_page_layoutpage_null_false.rb +0 -6
- data/db/migrate/20200519073500_remove_visible_from_alchemy_pages.rb +0 -24
- data/db/migrate/20200617110713_create_alchemy_picture_thumbs.rb +0 -22
- data/db/migrate/20200907111332_remove_tri_state_booleans.rb +0 -33
- data/db/migrate/20201207131309_create_page_versions.rb +0 -19
- data/db/migrate/20201207135820_add_page_version_id_to_alchemy_elements.rb +0 -76
- data/db/migrate/20210205143548_rename_public_on_and_public_until_on_alchemy_pages.rb +0 -10
- data/db/migrate/20210326105046_add_sanitized_body_to_alchemy_essence_richtexts.rb +0 -7
- data/db/migrate/20210406093436_add_alchemy_essence_headlines.rb +0 -12
- data/db/migrate/20210506135919_create_essence_audios.rb +0 -19
- data/db/migrate/20210506140258_create_essence_videos.rb +0 -23
- data/db/migrate/20210508091432_create_alchemy_ingredients.rb +0 -22
- data/db/migrate/20220514072456_restrict_on_delete_page_id_foreign_key_from_alchemy_nodes.rb +0 -13
- data/db/migrate/20220622130905_add_playsinline_to_alchemy_essence_videos.rb +0 -9
- data/lib/alchemy/essence.rb +0 -250
- data/lib/alchemy/tasks/usage.rb +0 -34
- data/lib/alchemy/test_support/essence_shared_examples.rb +0 -271
- data/lib/alchemy/test_support/factories/content_factory.rb +0 -20
- data/lib/alchemy/test_support/factories/essence_audio_factory.rb +0 -7
- data/lib/alchemy/test_support/factories/essence_file_factory.rb +0 -7
- data/lib/alchemy/test_support/factories/essence_page_factory.rb +0 -7
- data/lib/alchemy/test_support/factories/essence_picture_factory.rb +0 -11
- data/lib/alchemy/test_support/factories/essence_text_factory.rb +0 -7
- data/lib/alchemy/test_support/factories/essence_video_factory.rb +0 -7
- data/lib/alchemy/upgrader/five_point_zero.rb +0 -41
- data/lib/alchemy/upgrader/six_point_zero.rb +0 -21
- data/lib/alchemy/upgrader/tasks/add_page_versions.rb +0 -33
- data/lib/alchemy/upgrader/tasks/element_views_updater.rb +0 -34
- data/lib/alchemy/upgrader/tasks/harden_gutentag_migrations.rb +0 -29
- data/lib/alchemy/upgrader/tasks/ingredients_migrator.rb +0 -73
- data/lib/generators/alchemy/essence/essence_generator.rb +0 -49
- data/lib/generators/alchemy/essence/templates/editor.html.erb +0 -17
- data/lib/generators/alchemy/essence/templates/view.html.erb +0 -2
- data/lib/generators/alchemy/install/files/babel.config.js +0 -64
- data/lib/tasks/alchemy/usage.rake +0 -44
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
class RestrictOnDeletePageIdForeignKeyFromAlchemyNodes < ActiveRecord::Migration[6.0]
|
|
4
|
-
def up
|
|
5
|
-
remove_foreign_key :alchemy_nodes, :alchemy_pages
|
|
6
|
-
add_foreign_key :alchemy_nodes, :alchemy_pages, column: :page_id, on_delete: :restrict
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
def down
|
|
10
|
-
remove_foreign_key :alchemy_nodes, :alchemy_pages
|
|
11
|
-
add_foreign_key :alchemy_nodes, :alchemy_pages, column: :page_id, on_delete: :cascade
|
|
12
|
-
end
|
|
13
|
-
end
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
class AddPlaysinlineToAlchemyEssenceVideos < ActiveRecord::Migration[6.0]
|
|
4
|
-
def change
|
|
5
|
-
return if column_exists?(:alchemy_essence_videos, :playsinline)
|
|
6
|
-
|
|
7
|
-
add_column :alchemy_essence_videos, :playsinline, :boolean, default: false, null: false
|
|
8
|
-
end
|
|
9
|
-
end
|
data/lib/alchemy/essence.rb
DELETED
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "active_record"
|
|
4
|
-
|
|
5
|
-
module Alchemy #:nodoc:
|
|
6
|
-
module Essence #:nodoc:
|
|
7
|
-
def self.included(base)
|
|
8
|
-
base.extend(ClassMethods)
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
# Delivers various methods we need for Essences in Alchemy.
|
|
12
|
-
#
|
|
13
|
-
# To turn a model into an essence call acts_as_essence inside your model and you will get:
|
|
14
|
-
# * validations
|
|
15
|
-
# * several getters (ie: page, element, content, ingredient, preview_text)
|
|
16
|
-
#
|
|
17
|
-
module ClassMethods
|
|
18
|
-
# Turn any active record model into an essence by calling this class method
|
|
19
|
-
#
|
|
20
|
-
# @option options [String || Symbol] ingredient_column ('body')
|
|
21
|
-
# specifies the column name you use for storing the content in the database (default: +body+)
|
|
22
|
-
# @option options [String || Symbol] validate_column (ingredient_column)
|
|
23
|
-
# The column the the validations run against.
|
|
24
|
-
# @option options [String || Symbol] preview_text_column (ingredient_column)
|
|
25
|
-
# Specify the column for the preview_text method.
|
|
26
|
-
# @deprecated
|
|
27
|
-
def acts_as_essence(options = {})
|
|
28
|
-
if !DEPRECATED_ESSENCE_CLASSES.include?(name)
|
|
29
|
-
Alchemy::Deprecation.warn "Please create a custom Alchemy::Ingredient for #{name} instead"
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
register_as_essence_association!
|
|
33
|
-
|
|
34
|
-
configuration = {
|
|
35
|
-
ingredient_column: "body",
|
|
36
|
-
}.update(options)
|
|
37
|
-
|
|
38
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
39
|
-
attr_writer :validation_errors
|
|
40
|
-
include Alchemy::Essence::InstanceMethods
|
|
41
|
-
|
|
42
|
-
validate :validate_ingredient, on: :update, if: -> { validations.any? }
|
|
43
|
-
|
|
44
|
-
has_one :content, as: :essence, class_name: "Alchemy::Content", inverse_of: :essence
|
|
45
|
-
has_one :element, through: :content, class_name: "Alchemy::Element"
|
|
46
|
-
has_one :page, through: :element, class_name: "Alchemy::Page"
|
|
47
|
-
|
|
48
|
-
scope :available, -> { joins(:element).merge(Alchemy::Element.published) }
|
|
49
|
-
scope :from_element, ->(name) { joins(:element).where(Element.table_name => { name: name }) }
|
|
50
|
-
|
|
51
|
-
delegate :restricted?, to: :page, allow_nil: true
|
|
52
|
-
delegate :public?, to: :element, allow_nil: true
|
|
53
|
-
|
|
54
|
-
after_update :touch_element
|
|
55
|
-
|
|
56
|
-
def acts_as_essence_class
|
|
57
|
-
#{name}
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def ingredient_column
|
|
61
|
-
'#{configuration[:ingredient_column]}'
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def validation_column
|
|
65
|
-
'#{configuration[:validate_column] || configuration[:ingredient_column]}'
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def preview_text_column
|
|
69
|
-
'#{configuration[:preview_text_column] || configuration[:ingredient_column]}'
|
|
70
|
-
end
|
|
71
|
-
RUBY
|
|
72
|
-
|
|
73
|
-
if configuration[:belongs_to]
|
|
74
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
75
|
-
belongs_to :ingredient_association, **#{configuration[:belongs_to]}
|
|
76
|
-
|
|
77
|
-
alias_method :#{configuration[:ingredient_column]}, :ingredient_association
|
|
78
|
-
alias_method :#{configuration[:ingredient_column]}=, :ingredient_association=
|
|
79
|
-
RUBY
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
private
|
|
84
|
-
|
|
85
|
-
# Register the current class as has_many association on +Alchemy::Page+ and +Alchemy::Element+ models
|
|
86
|
-
def register_as_essence_association!
|
|
87
|
-
klass_name = model_name.to_s
|
|
88
|
-
arguments = [:has_many, klass_name.demodulize.tableize.to_sym]
|
|
89
|
-
kwargs = { through: :contents, source: :essence, source_type: klass_name }
|
|
90
|
-
%w(Page Element).each { |k| "Alchemy::#{k}".constantize.send(*arguments, **kwargs) }
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
module InstanceMethods
|
|
95
|
-
# Essence Validations:
|
|
96
|
-
#
|
|
97
|
-
# Essence validations can be set inside the config/elements.yml file.
|
|
98
|
-
#
|
|
99
|
-
# Supported validations are:
|
|
100
|
-
#
|
|
101
|
-
# * presence
|
|
102
|
-
# * uniqueness
|
|
103
|
-
# * format
|
|
104
|
-
#
|
|
105
|
-
# format needs to come with a regex or a predefined matcher string as its value.
|
|
106
|
-
# There are already predefined format matchers listed in the config/alchemy/config.yml file.
|
|
107
|
-
# It is also possible to add own format matchers there.
|
|
108
|
-
#
|
|
109
|
-
# Example of format matchers in config/alchemy/config.yml:
|
|
110
|
-
#
|
|
111
|
-
# format_matchers:
|
|
112
|
-
# email: !ruby/regexp '/\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/'
|
|
113
|
-
# url: !ruby/regexp '/\A[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?\z/ix'
|
|
114
|
-
# ssl: !ruby/regexp '/https:\/\/[\S]+/'
|
|
115
|
-
#
|
|
116
|
-
# Example of an element definition with essence validations:
|
|
117
|
-
#
|
|
118
|
-
# - name: person
|
|
119
|
-
# contents:
|
|
120
|
-
# - name: name
|
|
121
|
-
# type: EssenceText
|
|
122
|
-
# validate: [presence]
|
|
123
|
-
# - name: email
|
|
124
|
-
# type: EssenceText
|
|
125
|
-
# validate: [format: 'email']
|
|
126
|
-
# - name: homepage
|
|
127
|
-
# type: EssenceText
|
|
128
|
-
# validate: [format: !ruby/regexp '^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$']
|
|
129
|
-
#
|
|
130
|
-
# Example of an element definition with chained validations.
|
|
131
|
-
#
|
|
132
|
-
# - name: person
|
|
133
|
-
# contents:
|
|
134
|
-
# - name: name
|
|
135
|
-
# type: EssenceText
|
|
136
|
-
# validate: [presence, uniqueness, format: 'name']
|
|
137
|
-
#
|
|
138
|
-
def validate_ingredient
|
|
139
|
-
validations.each do |validation|
|
|
140
|
-
if validation.respond_to?(:keys)
|
|
141
|
-
validation.map do |key, value|
|
|
142
|
-
send("validate_#{key}", value)
|
|
143
|
-
end
|
|
144
|
-
else
|
|
145
|
-
send("validate_#{validation}")
|
|
146
|
-
end
|
|
147
|
-
end
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
def validations
|
|
151
|
-
@validations ||= definition.present? ? definition["validate"] || [] : []
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
def validation_errors
|
|
155
|
-
@validation_errors ||= []
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
def validate_presence(validate = true)
|
|
159
|
-
if validate && ingredient.blank?
|
|
160
|
-
errors.add(ingredient_column, :blank)
|
|
161
|
-
validation_errors << :blank
|
|
162
|
-
end
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
def validate_uniqueness(validate = true)
|
|
166
|
-
return if !validate || !public?
|
|
167
|
-
|
|
168
|
-
if duplicates.any?
|
|
169
|
-
errors.add(ingredient_column, :taken)
|
|
170
|
-
validation_errors << :taken
|
|
171
|
-
end
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
def validate_format(format)
|
|
175
|
-
matcher = Config.get("format_matchers")[format] || format
|
|
176
|
-
if ingredient.to_s.match(Regexp.new(matcher)).nil?
|
|
177
|
-
errors.add(ingredient_column, :invalid)
|
|
178
|
-
validation_errors << :invalid
|
|
179
|
-
end
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
def duplicates
|
|
183
|
-
acts_as_essence_class
|
|
184
|
-
.available
|
|
185
|
-
.from_element(element.name)
|
|
186
|
-
.where(ingredient_column.to_s => ingredient)
|
|
187
|
-
.where.not(id: id)
|
|
188
|
-
end
|
|
189
|
-
|
|
190
|
-
# Returns the value stored from the database column that is configured as ingredient column.
|
|
191
|
-
def ingredient
|
|
192
|
-
if respond_to?(ingredient_column)
|
|
193
|
-
send(ingredient_column)
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
# Sets the value stored in the database column that is configured as ingredient column.
|
|
198
|
-
def ingredient=(value)
|
|
199
|
-
if respond_to?(ingredient_setter_method)
|
|
200
|
-
send(ingredient_setter_method, value)
|
|
201
|
-
end
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
# Returns the setter method for ingredient column
|
|
205
|
-
def ingredient_setter_method
|
|
206
|
-
ingredient_column.to_s + "="
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
# Essence definition from config/elements.yml
|
|
210
|
-
def definition
|
|
211
|
-
return {} if element.nil? || element.content_definitions.nil?
|
|
212
|
-
|
|
213
|
-
element.content_definitions.detect { |c| c["name"] == content.name } || {}
|
|
214
|
-
end
|
|
215
|
-
|
|
216
|
-
# Touches element. Called after save.
|
|
217
|
-
def touch_element
|
|
218
|
-
element&.touch
|
|
219
|
-
end
|
|
220
|
-
|
|
221
|
-
# Returns the first x (default 30) characters of ingredient for the Element#preview_text method.
|
|
222
|
-
#
|
|
223
|
-
def preview_text(maxlength = 30)
|
|
224
|
-
send(preview_text_column).to_s[0..maxlength - 1]
|
|
225
|
-
end
|
|
226
|
-
|
|
227
|
-
def open_link_in_new_window?
|
|
228
|
-
respond_to?(:link_target) && link_target == "blank"
|
|
229
|
-
end
|
|
230
|
-
|
|
231
|
-
def partial_name
|
|
232
|
-
self.class.name.split("::").last.underscore
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
def acts_as_essence?
|
|
236
|
-
acts_as_essence_class.present?
|
|
237
|
-
end
|
|
238
|
-
|
|
239
|
-
def to_partial_path
|
|
240
|
-
"alchemy/essences/#{partial_name}_view"
|
|
241
|
-
end
|
|
242
|
-
|
|
243
|
-
def has_tinymce?
|
|
244
|
-
false
|
|
245
|
-
end
|
|
246
|
-
end
|
|
247
|
-
end
|
|
248
|
-
end
|
|
249
|
-
|
|
250
|
-
ActiveRecord::Base.include(Alchemy::Essence)
|
data/lib/alchemy/tasks/usage.rb
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Alchemy
|
|
4
|
-
module Tasks
|
|
5
|
-
module Usage
|
|
6
|
-
extend self
|
|
7
|
-
|
|
8
|
-
def elements_count_by_name
|
|
9
|
-
res = Alchemy::Element.all
|
|
10
|
-
.select("name, COUNT(*) AS count")
|
|
11
|
-
.group(:name)
|
|
12
|
-
.order("count DESC, name ASC")
|
|
13
|
-
.map { |e| {"name" => e.name, "count" => e.count} }
|
|
14
|
-
Alchemy::Element.definitions.map do |definition|
|
|
15
|
-
count = res.find { |r| r["name"] == definition["name"] }&.fetch("count") || 0
|
|
16
|
-
definition["count"] = count
|
|
17
|
-
definition
|
|
18
|
-
end.sort_by { |r| -1 * r["count"] }
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def pages_count_by_type
|
|
22
|
-
res = Alchemy::Page.all
|
|
23
|
-
.select("page_layout, COUNT(*) AS count")
|
|
24
|
-
.group(:page_layout)
|
|
25
|
-
.order("count DESC, page_layout ASC")
|
|
26
|
-
.map { |p| {"page_layout" => p.page_layout, "count" => p.count} }
|
|
27
|
-
Alchemy::PageLayout.all.reject { |page_layout| res.map { |p| p["page_layout"] }.include? page_layout["name"] }.sort_by { |d| d["name"] }.each do |page_layout|
|
|
28
|
-
res << {"page_layout" => page_layout["name"], "count" => 0}
|
|
29
|
-
end
|
|
30
|
-
res
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
@@ -1,271 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "shoulda-matchers"
|
|
4
|
-
|
|
5
|
-
RSpec.shared_examples_for "an essence" do
|
|
6
|
-
let(:element) { Alchemy::Element.new }
|
|
7
|
-
let(:content) { Alchemy::Content.new(name: "foo") }
|
|
8
|
-
let(:content_definition) { { "name" => "foo" } }
|
|
9
|
-
|
|
10
|
-
it "touches the element after save" do
|
|
11
|
-
element = FactoryBot.create(:alchemy_element)
|
|
12
|
-
content = FactoryBot.create(:alchemy_content, element: element, essence: essence, essence_type: essence.class.name)
|
|
13
|
-
|
|
14
|
-
element.update_column(:updated_at, 3.days.ago)
|
|
15
|
-
content.essence.update(essence.ingredient_column.to_sym => ingredient_value)
|
|
16
|
-
|
|
17
|
-
element.reload
|
|
18
|
-
expect(element.updated_at).to be_within(3.seconds).of(Time.current)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
it "should have correct partial path" do
|
|
22
|
-
underscored_essence = essence.class.name.demodulize.underscore
|
|
23
|
-
expect(essence.to_partial_path).to eq("alchemy/essences/#{underscored_essence}_view")
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
describe "#definition" do
|
|
27
|
-
subject { essence.definition }
|
|
28
|
-
|
|
29
|
-
context "without element" do
|
|
30
|
-
it { is_expected.to eq({}) }
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
context "with element" do
|
|
34
|
-
before do
|
|
35
|
-
expect(essence).to receive(:element).at_least(:once).and_return(element)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
context "but without content definitions" do
|
|
39
|
-
it { is_expected.to eq({}) }
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
context "and content definitions" do
|
|
43
|
-
before do
|
|
44
|
-
allow(essence).to receive(:content).and_return(content)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
context "containing the content name" do
|
|
48
|
-
before do
|
|
49
|
-
expect(element).to receive(:content_definitions).at_least(:once).and_return([content_definition])
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
it "returns the content definition" do
|
|
53
|
-
is_expected.to eq(content_definition)
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
context "not containing the content name" do
|
|
58
|
-
before do
|
|
59
|
-
expect(element).to receive(:content_definitions).at_least(:once).and_return([])
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
it { is_expected.to eq({}) }
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
describe "#ingredient=" do
|
|
69
|
-
it "should set the value to ingredient column" do
|
|
70
|
-
essence.ingredient = ingredient_value
|
|
71
|
-
expect(essence.ingredient).to eq ingredient_value
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
describe "validations" do
|
|
76
|
-
context "without essence definition in elements.yml" do
|
|
77
|
-
it "should return an empty array" do
|
|
78
|
-
allow(essence).to receive(:definition).and_return nil
|
|
79
|
-
expect(essence.validations).to eq([])
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
context "without validations defined in essence definition in elements.yml" do
|
|
84
|
-
it "should return an empty array" do
|
|
85
|
-
allow(essence).to receive(:definition).and_return({ name: "test", type: "EssenceText" })
|
|
86
|
-
expect(essence.validations).to eq([])
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
describe "presence" do
|
|
91
|
-
context "with string given as validation type" do
|
|
92
|
-
before do
|
|
93
|
-
allow(essence).to receive(:definition).and_return({ "validate" => ["presence"] })
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
context "when the ingredient column is empty" do
|
|
97
|
-
before do
|
|
98
|
-
essence.update(essence.ingredient_column.to_sym => nil)
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
it "should not be valid" do
|
|
102
|
-
expect(essence).to_not be_valid
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
context "when the ingredient column is not nil" do
|
|
107
|
-
before do
|
|
108
|
-
essence.update(essence.ingredient_column.to_sym => ingredient_value)
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
it "should be valid" do
|
|
112
|
-
expect(essence).to be_valid
|
|
113
|
-
end
|
|
114
|
-
end
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
context "with hash given as validation type" do
|
|
118
|
-
context "where the value is true" do
|
|
119
|
-
before do
|
|
120
|
-
allow(essence).to receive(:definition).and_return({ "validate" => [{ "presence" => true }] })
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
context "when the ingredient column is empty" do
|
|
124
|
-
before do
|
|
125
|
-
essence.update(essence.ingredient_column.to_sym => nil)
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
it "should not be valid" do
|
|
129
|
-
expect(essence).to_not be_valid
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
context "when the ingredient column is not nil" do
|
|
134
|
-
before do
|
|
135
|
-
essence.update(essence.ingredient_column.to_sym => ingredient_value)
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
it "should be valid" do
|
|
139
|
-
expect(essence).to be_valid
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
context "where the value is false" do
|
|
145
|
-
before do
|
|
146
|
-
allow(essence).to receive(:definition).and_return({ "validate" => [{ "presence" => false }] })
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
it "should be valid" do
|
|
150
|
-
expect(essence).to be_valid
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
|
-
end
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
describe "uniqueness" do
|
|
157
|
-
before do
|
|
158
|
-
allow(essence).to receive(:element).and_return(FactoryBot.create(:alchemy_element))
|
|
159
|
-
essence.update(essence.ingredient_column.to_sym => ingredient_value)
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
context "with string given as validation type" do
|
|
163
|
-
before do
|
|
164
|
-
expect(essence).to receive(:definition).at_least(:once).and_return({ "validate" => ["uniqueness"] })
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
context "when a duplicate exists" do
|
|
168
|
-
before do
|
|
169
|
-
allow(essence).to receive(:duplicates).and_return([essence.dup])
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
it "should not be valid" do
|
|
173
|
-
expect(essence).to_not be_valid
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
context "when validated essence is not public" do
|
|
177
|
-
before do
|
|
178
|
-
expect(essence).to receive(:public?).and_return(false)
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
it "should be valid" do
|
|
182
|
-
expect(essence).to be_valid
|
|
183
|
-
end
|
|
184
|
-
end
|
|
185
|
-
end
|
|
186
|
-
|
|
187
|
-
context "when no duplicate exists" do
|
|
188
|
-
before do
|
|
189
|
-
expect(essence).to receive(:duplicates).and_return([])
|
|
190
|
-
end
|
|
191
|
-
|
|
192
|
-
it "should be valid" do
|
|
193
|
-
expect(essence).to be_valid
|
|
194
|
-
end
|
|
195
|
-
end
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
context "with hash given as validation type" do
|
|
199
|
-
context "where the value is true" do
|
|
200
|
-
before do
|
|
201
|
-
expect(essence).to receive(:definition).at_least(:once).and_return({ "validate" => [{ "uniqueness" => true }] })
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
context "when a duplicate exists" do
|
|
205
|
-
before do
|
|
206
|
-
allow(essence).to receive(:duplicates).and_return([essence.dup])
|
|
207
|
-
end
|
|
208
|
-
|
|
209
|
-
it "should not be valid" do
|
|
210
|
-
expect(essence).to_not be_valid
|
|
211
|
-
end
|
|
212
|
-
|
|
213
|
-
context "when validated essence is not public" do
|
|
214
|
-
before do
|
|
215
|
-
expect(essence).to receive(:public?).and_return(false)
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
it "should be valid" do
|
|
219
|
-
expect(essence).to be_valid
|
|
220
|
-
end
|
|
221
|
-
end
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
context "when no duplicate exists" do
|
|
225
|
-
before do
|
|
226
|
-
expect(essence).to receive(:duplicates).and_return([])
|
|
227
|
-
end
|
|
228
|
-
|
|
229
|
-
it "should be valid" do
|
|
230
|
-
expect(essence).to be_valid
|
|
231
|
-
end
|
|
232
|
-
end
|
|
233
|
-
end
|
|
234
|
-
|
|
235
|
-
context "where the value is false" do
|
|
236
|
-
before do
|
|
237
|
-
allow(essence).to receive(:definition).and_return({ "validate" => [{ "uniqueness" => false }] })
|
|
238
|
-
end
|
|
239
|
-
|
|
240
|
-
it "should be valid" do
|
|
241
|
-
expect(essence).to be_valid
|
|
242
|
-
end
|
|
243
|
-
end
|
|
244
|
-
end
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
describe "#acts_as_essence?" do
|
|
248
|
-
it "should return true" do
|
|
249
|
-
expect(essence.acts_as_essence?).to be_truthy
|
|
250
|
-
end
|
|
251
|
-
end
|
|
252
|
-
end
|
|
253
|
-
|
|
254
|
-
context "delegations" do
|
|
255
|
-
it { should delegate_method(:restricted?).to(:page) }
|
|
256
|
-
it { should delegate_method(:public?).to(:element) }
|
|
257
|
-
end
|
|
258
|
-
|
|
259
|
-
describe "essence relations" do
|
|
260
|
-
let(:page) { FactoryBot.create(:alchemy_page, :restricted) }
|
|
261
|
-
let(:element) { FactoryBot.create(:alchemy_element) }
|
|
262
|
-
|
|
263
|
-
it "registers itself on page as essence relation" do
|
|
264
|
-
expect(page.respond_to?(essence.class.model_name.route_key)).to be(true)
|
|
265
|
-
end
|
|
266
|
-
|
|
267
|
-
it "registers itself on element as essence relation" do
|
|
268
|
-
expect(element.respond_to?(essence.class.model_name.route_key)).to be(true)
|
|
269
|
-
end
|
|
270
|
-
end
|
|
271
|
-
end
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
FactoryBot.define do
|
|
4
|
-
factory :alchemy_content, class: "Alchemy::Content" do
|
|
5
|
-
name { "text" }
|
|
6
|
-
essence_type { "Alchemy::EssenceText" }
|
|
7
|
-
association :essence, factory: :alchemy_essence_text
|
|
8
|
-
association :element, factory: :alchemy_element
|
|
9
|
-
|
|
10
|
-
trait :essence_file do
|
|
11
|
-
essence_type { "Alchemy::EssenceFile" }
|
|
12
|
-
association :essence, factory: :alchemy_essence_file
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
trait :essence_picture do
|
|
16
|
-
essence_type { "Alchemy::EssencePicture" }
|
|
17
|
-
association :essence, factory: :alchemy_essence_picture
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
FactoryBot.define do
|
|
4
|
-
factory :alchemy_essence_picture, class: "Alchemy::EssencePicture" do
|
|
5
|
-
picture factory: :alchemy_picture
|
|
6
|
-
|
|
7
|
-
trait :with_content do
|
|
8
|
-
association :content, factory: :alchemy_content
|
|
9
|
-
end
|
|
10
|
-
end
|
|
11
|
-
end
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "tasks/harden_gutentag_migrations"
|
|
4
|
-
|
|
5
|
-
module Alchemy
|
|
6
|
-
class Upgrader::FivePointZero < Upgrader
|
|
7
|
-
class << self
|
|
8
|
-
def install_gutentag_migrations
|
|
9
|
-
desc "Install Gutentag migrations"
|
|
10
|
-
Rake::Task["gutentag:install:migrations"].invoke
|
|
11
|
-
Alchemy::Upgrader::Tasks::HardenGutentagMigrations.new.patch_migrations
|
|
12
|
-
Rake::Task["db:migrate"].invoke
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def remove_layout_roots
|
|
16
|
-
desc "Remove layout root pages"
|
|
17
|
-
layout_roots = Alchemy::Page.where(layoutpage: true).where("name LIKE 'Layoutroot for%'")
|
|
18
|
-
if layout_roots.size.positive?
|
|
19
|
-
log "Removing #{layout_roots.size} layout root pages."
|
|
20
|
-
layout_roots.delete_all
|
|
21
|
-
Alchemy::Page.where(layoutpage: true).update_all(parent_id: nil)
|
|
22
|
-
log "Done.", :success
|
|
23
|
-
else
|
|
24
|
-
log "No layout root pages found.", :skip
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def remove_root_page
|
|
29
|
-
desc "Remove root page"
|
|
30
|
-
root_page = Alchemy::Page.find_by(parent_id: nil, name: "Root")
|
|
31
|
-
if root_page
|
|
32
|
-
Alchemy::Page.where(parent_id: root_page.id).update_all(parent_id: nil)
|
|
33
|
-
root_page.delete
|
|
34
|
-
log "Done.", :success
|
|
35
|
-
else
|
|
36
|
-
log "Root page not found.", :skip
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|