alchemy_cms 3.5.0 → 3.6.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 (118) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +82 -26
  3. data/.travis.yml +1 -1
  4. data/CHANGELOG.md +23 -1
  5. data/README.md +14 -5
  6. data/Rakefile +0 -1
  7. data/alchemy_cms.gemspec +2 -5
  8. data/app/assets/images/alchemy/alchemy-logo.png +0 -0
  9. data/app/assets/javascripts/alchemy/admin.js +1 -1
  10. data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +4 -8
  11. data/app/assets/javascripts/alchemy/alchemy.buttons.js.coffee +2 -2
  12. data/app/assets/javascripts/alchemy/alchemy.datepicker.js.coffee +18 -27
  13. data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +1 -1
  14. data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +3 -8
  15. data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +1 -1
  16. data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +0 -1
  17. data/app/assets/javascripts/alchemy/alchemy.page_sorter.js +22 -46
  18. data/app/assets/javascripts/alchemy/alchemy.preview_window.js.coffee +1 -1
  19. data/app/assets/javascripts/alchemy/alchemy.sitemap.js.coffee +2 -2
  20. data/app/assets/javascripts/alchemy/alchemy.spinner.js +32 -0
  21. data/app/assets/javascripts/alchemy/alchemy.tinymce.js.coffee +1 -1
  22. data/app/assets/javascripts/alchemy/templates/index.js +1 -0
  23. data/app/assets/javascripts/alchemy/templates/spinner.hbs +7 -0
  24. data/app/assets/stylesheets/alchemy/_extends.scss +1 -0
  25. data/app/assets/stylesheets/alchemy/admin.scss +1 -0
  26. data/app/assets/stylesheets/alchemy/base.scss +1 -7
  27. data/app/assets/stylesheets/alchemy/buttons.scss +1 -5
  28. data/app/assets/stylesheets/alchemy/dialogs.scss +0 -4
  29. data/app/assets/stylesheets/alchemy/elements.scss +2 -6
  30. data/app/assets/stylesheets/alchemy/frame.scss +0 -5
  31. data/app/assets/stylesheets/alchemy/image_library.scss +0 -13
  32. data/app/assets/stylesheets/alchemy/sitemap.scss +5 -34
  33. data/app/assets/stylesheets/alchemy/spinner.scss +52 -0
  34. data/app/controllers/alchemy/admin/attachments_controller.rb +12 -11
  35. data/app/controllers/alchemy/admin/base_controller.rb +3 -7
  36. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +2 -1
  37. data/app/controllers/alchemy/admin/languages_controller.rb +3 -8
  38. data/app/controllers/alchemy/admin/pictures_controller.rb +11 -7
  39. data/app/controllers/alchemy/admin/resources_controller.rb +1 -1
  40. data/app/controllers/alchemy/attachments_controller.rb +2 -0
  41. data/app/controllers/alchemy/base_controller.rb +4 -5
  42. data/app/controllers/concerns/alchemy/admin/uploader_responses.rb +1 -1
  43. data/app/helpers/alchemy/admin/base_helper.rb +17 -8
  44. data/app/helpers/alchemy/admin/tags_helper.rb +31 -18
  45. data/app/helpers/alchemy/base_helper.rb +1 -1
  46. data/app/helpers/alchemy/pages_helper.rb +4 -7
  47. data/app/models/alchemy/attachment.rb +4 -0
  48. data/app/models/alchemy/cell.rb +1 -1
  49. data/app/models/alchemy/element.rb +6 -12
  50. data/app/models/alchemy/element/definitions.rb +2 -2
  51. data/app/models/alchemy/element/element_contents.rb +1 -1
  52. data/app/models/alchemy/essence_picture_view.rb +14 -2
  53. data/app/models/alchemy/language.rb +4 -4
  54. data/app/models/alchemy/page.rb +25 -28
  55. data/app/models/alchemy/page/page_elements.rb +1 -1
  56. data/app/models/alchemy/page/page_natures.rb +1 -1
  57. data/app/models/alchemy/picture.rb +5 -1
  58. data/app/models/alchemy/site.rb +27 -12
  59. data/app/views/alchemy/admin/attachments/_tag_list.html.erb +14 -13
  60. data/app/views/alchemy/admin/dashboard/info.html.erb +1 -1
  61. data/app/views/alchemy/admin/layoutpages/edit.html.erb +1 -1
  62. data/app/views/alchemy/admin/pages/_create_language_form.html.erb +1 -1
  63. data/app/views/alchemy/admin/pages/_form.html.erb +1 -1
  64. data/app/views/alchemy/admin/pages/_new_page_form.html.erb +1 -1
  65. data/app/views/alchemy/admin/pages/_page.html.erb +1 -1
  66. data/app/views/alchemy/admin/pages/_sitemap.html.erb +2 -2
  67. data/app/views/alchemy/admin/pages/configure_external.html.erb +1 -1
  68. data/app/views/alchemy/admin/pages/index.html.erb +5 -7
  69. data/app/views/alchemy/admin/pages/sort.html.erb +19 -0
  70. data/app/views/alchemy/admin/pages/update.js.erb +1 -1
  71. data/app/views/alchemy/admin/pictures/_archive.html.erb +19 -19
  72. data/app/views/alchemy/admin/pictures/_tag_list.html.erb +3 -4
  73. data/app/views/alchemy/admin/resources/_tag_list.html.erb +3 -4
  74. data/app/views/alchemy/admin/resources/edit.html.erb +1 -1
  75. data/app/views/alchemy/admin/resources/new.html.erb +1 -1
  76. data/app/views/alchemy/pages/_meta_data.html.erb +1 -1
  77. data/app/views/alchemy/pages/show.rss.builder +0 -2
  78. data/app/views/alchemy/welcome.html.erb +1 -1
  79. data/app/views/layouts/alchemy/admin.html.erb +1 -1
  80. data/config/locales/alchemy.de.yml +4 -4
  81. data/config/locales/alchemy.en.yml +4 -4
  82. data/config/locales/alchemy.es.yml +3 -3
  83. data/config/locales/alchemy.fr.yml +4 -4
  84. data/config/locales/alchemy.it.yml +3 -3
  85. data/config/locales/alchemy.nl.yml +4 -4
  86. data/config/locales/alchemy.ru.yml +3 -3
  87. data/lib/alchemy/auth_accessors.rb +6 -6
  88. data/lib/alchemy/cache_digests/template_tracker.rb +5 -5
  89. data/lib/alchemy/controller_actions.rb +1 -6
  90. data/lib/alchemy/engine.rb +0 -53
  91. data/lib/alchemy/errors.rb +12 -3
  92. data/lib/alchemy/i18n.rb +1 -1
  93. data/lib/alchemy/logger.rb +1 -1
  94. data/lib/alchemy/page_layout.rb +5 -5
  95. data/lib/alchemy/seeder.rb +16 -49
  96. data/lib/alchemy/tasks/helpers.rb +1 -1
  97. data/lib/alchemy/test_support/config_stubbing.rb +28 -0
  98. data/lib/alchemy/test_support/essence_shared_examples.rb +6 -6
  99. data/lib/alchemy/test_support/factories/language_factory.rb +1 -1
  100. data/lib/alchemy/test_support/factories/page_factory.rb +7 -0
  101. data/lib/alchemy/test_support/factories/site_factory.rb +6 -0
  102. data/lib/alchemy/test_support/shared_contexts.rb +14 -0
  103. data/lib/alchemy/test_support/shared_uploader_examples.rb +10 -0
  104. data/lib/alchemy/touching.rb +1 -1
  105. data/lib/alchemy/version.rb +1 -1
  106. data/lib/alchemy_cms.rb +56 -1
  107. data/lib/{alchemy/kaminari → kaminari}/scoped_pagination_url_helper.rb +0 -0
  108. data/lib/rails/generators/alchemy/base.rb +1 -1
  109. data/lib/rails/generators/alchemy/elements/elements_generator.rb +2 -1
  110. data/lib/rails/generators/alchemy/page_layouts/page_layouts_generator.rb +2 -1
  111. data/lib/rails/generators/alchemy/site_layouts/site_layouts_generator.rb +2 -1
  112. data/lib/tasks/alchemy/tidy.rake +91 -89
  113. data/lib/tasks/alchemy/upgrade.rake +15 -15
  114. metadata +29 -14
  115. data/app/assets/javascripts/alchemy/alchemy.spinner.js.coffee +0 -49
  116. data/app/views/alchemy/admin/pages/sort.js.erb +0 -4
  117. data/vendor/assets/javascripts/handlebars.js +0 -4608
  118. data/vendor/assets/javascripts/spin.min.js +0 -1
@@ -12,7 +12,7 @@ module Alchemy
12
12
  def database_config
13
13
  raise "Could not find #{database_config_file}!" if !File.exist?(database_config_file)
14
14
  @database_config ||= begin
15
- config_file = YAML.load(ERB.new(File.read(database_config_file)).result)
15
+ config_file = YAML.safe_load(ERB.new(File.read(database_config_file)).result, [], [], true)
16
16
  config_file.fetch(environment)
17
17
  rescue KeyError
18
18
  raise "Database configuration for #{environment} not found!"
@@ -0,0 +1,28 @@
1
+ module Alchemy
2
+ module TestSupport
3
+ # Allows you to stub the Alchemy configuration in your specs
4
+ #
5
+ # Require and include this file in your RSpec config.
6
+ #
7
+ # RSpec.configure do |config|
8
+ # config.include Alchemy::TestSupport::ConfigStubbing
9
+ # end
10
+ #
11
+ module ConfigStubbing
12
+ # Stub a key from the Alchemy config
13
+ #
14
+ # @param key [Symbol] The configuration key you want to stub
15
+ # @param value [Object] The value you want to return instead of the original one
16
+ #
17
+ def stub_alchemy_config(key, value)
18
+ allow(Alchemy::Config).to receive(:get) do |arg|
19
+ if arg == key
20
+ value
21
+ else
22
+ Alchemy::Config.show[arg.to_s]
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -7,13 +7,13 @@ shared_examples_for "an essence" do
7
7
 
8
8
  it "touches the content after update" do
9
9
  element = create(:alchemy_element)
10
- content = create(:alchemy_content, element: element)
11
- essence.save
12
- content.update(essence: essence, essence_type: essence.class.name)
13
- date = content.updated_at
14
- content.essence.update(essence.ingredient_column.to_sym => ingredient_value)
10
+ content = create(:alchemy_content, element: element, essence: essence, essence_type: essence.class.name)
11
+
12
+ content.update_column(:updated_at, 3.days.ago)
13
+ content.essence.update_attributes(essence.ingredient_column.to_sym => ingredient_value)
14
+
15
15
  content.reload
16
- expect(content.updated_at).not_to eq(date)
16
+ expect(content.updated_at).to be_within(3.seconds).of(Time.current)
17
17
  end
18
18
 
19
19
  it "should have correct partial path" do
@@ -9,7 +9,7 @@ FactoryGirl.define do
9
9
  frontpage_name 'Intro'
10
10
  page_layout { Alchemy::Config.get(:default_language)['page_layout'] }
11
11
  public true
12
- site { Alchemy::Site.first || FactoryGirl.create(:alchemy_site) }
12
+ site { Alchemy::Site.default }
13
13
 
14
14
  trait :klingon do
15
15
  name 'Klingon'
@@ -16,6 +16,13 @@ FactoryGirl.define do
16
16
  # Pass do_not_autogenerate: false to generate elements
17
17
  do_not_autogenerate true
18
18
 
19
+ trait :root do
20
+ name 'Root'
21
+ language nil
22
+ parent_id nil
23
+ page_layout nil
24
+ end
25
+
19
26
  trait :language_root do
20
27
  name 'Startseite'
21
28
  page_layout { language.page_layout }
@@ -5,6 +5,12 @@ FactoryGirl.define do
5
5
  name 'A Site'
6
6
  host 'domain.com'
7
7
 
8
+ trait :default do
9
+ public true
10
+ name Alchemy::Config.get(:default_site)['name']
11
+ host Alchemy::Config.get(:default_site)['host']
12
+ end
13
+
8
14
  trait :public do
9
15
  public true
10
16
  end
@@ -0,0 +1,14 @@
1
+ RSpec.shared_context 'with invalid file' do
2
+ let(:invalid_file) do
3
+ fixture_file_upload(
4
+ File.expand_path('../../../../spec/fixtures/users.yml', __FILE__),
5
+ 'text/x-yaml'
6
+ )
7
+ end
8
+
9
+ before do
10
+ allow(Alchemy::Attachment).to receive(:allowed_filetypes) do
11
+ ['png']
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,10 @@
1
+ RSpec.shared_examples_for "having a json uploader error message" do
2
+ it "renders json response with error message" do
3
+ subject
4
+ expect(response.content_type).to eq('application/json')
5
+ expect(response.status).to eq(422)
6
+ json = JSON.parse(response.body)
7
+ expect(json).to have_key('growl_message')
8
+ expect(json).to have_key('files')
9
+ end
10
+ end
@@ -2,7 +2,7 @@ module Alchemy
2
2
  module Touching
3
3
  # Touches the timestamps and userstamps
4
4
  #
5
- def touch
5
+ def touch(*)
6
6
  # Using update here, because we want the touch call to bubble up to the page.
7
7
  update(touchable_attributes)
8
8
  end
@@ -1,5 +1,5 @@
1
1
  module Alchemy
2
- VERSION = "3.5.0"
2
+ VERSION = "3.6.0"
3
3
 
4
4
  def self.version
5
5
  VERSION
@@ -2,4 +2,59 @@
2
2
  module Alchemy
3
3
  end
4
4
 
5
- require 'alchemy/engine'
5
+ # Require globally used external libraries
6
+ require 'acts_as_list'
7
+ require 'acts-as-taggable-on'
8
+ require 'action_view/dependency_tracker'
9
+ require 'active_model_serializers'
10
+ require 'awesome_nested_set'
11
+ require 'bourbon'
12
+ require 'cancan'
13
+ require 'dragonfly'
14
+ require 'handlebars_assets'
15
+ require 'jquery-rails'
16
+ require 'jquery-ui-rails'
17
+ require 'kaminari'
18
+ require 'non-stupid-digest-assets'
19
+ require 'ransack'
20
+ require 'request_store'
21
+ require 'responders'
22
+ require 'simple_form'
23
+ require 'select2-rails'
24
+ require 'turbolinks'
25
+ require 'userstamp'
26
+
27
+ # Require globally used Alchemy mixins
28
+ require_relative 'alchemy/ability_helper'
29
+ require_relative 'alchemy/admin/locale'
30
+ require_relative 'alchemy/auth_accessors'
31
+ require_relative 'alchemy/cache_digests/template_tracker'
32
+ require_relative 'alchemy/config'
33
+ require_relative 'alchemy/configuration_methods'
34
+ require_relative 'alchemy/controller_actions'
35
+ require_relative 'alchemy/errors'
36
+ require_relative 'alchemy/essence'
37
+ require_relative 'alchemy/filetypes'
38
+ require_relative 'alchemy/forms/builder'
39
+ require_relative 'alchemy/hints'
40
+ require_relative 'alchemy/i18n'
41
+ require_relative 'alchemy/logger'
42
+ require_relative 'alchemy/modules'
43
+ require_relative 'alchemy/name_conversions'
44
+ require_relative 'alchemy/on_page_layout'
45
+ require_relative 'alchemy/on_page_layout/callbacks_runner'
46
+ require_relative 'alchemy/page_layout'
47
+ require_relative 'alchemy/paths'
48
+ require_relative 'alchemy/permissions'
49
+ require_relative 'alchemy/picture_attributes'
50
+ require_relative 'alchemy/sass_support'
51
+ require_relative 'alchemy/ssl_protection'
52
+ require_relative 'alchemy/resource'
53
+ require_relative 'alchemy/tinymce'
54
+ require_relative 'alchemy/touching'
55
+
56
+ # Require hacks
57
+ require_relative 'kaminari/scoped_pagination_url_helper'
58
+
59
+ # Finally require Alchemy itself
60
+ require_relative 'alchemy/engine'
@@ -32,7 +32,7 @@ module Alchemy
32
32
  end
33
33
 
34
34
  def load_alchemy_yaml(name)
35
- YAML.load(ERB.new(File.read("#{Rails.root}/config/alchemy/#{name}")).result)
35
+ YAML.safe_load(ERB.new(File.read("#{Rails.root}/config/alchemy/#{name}")).result, [Regexp], [], true)
36
36
  rescue Errno::ENOENT
37
37
  puts "\nERROR: Could not read config/alchemy/#{name} file. Please run: rails generate alchemy:scaffold"
38
38
  end
@@ -8,6 +8,7 @@ module Alchemy
8
8
 
9
9
  def create_partials
10
10
  @elements = load_alchemy_yaml('elements.yml')
11
+ return unless @elements
11
12
  @elements.each do |element|
12
13
  @element = element
13
14
  @contents = element["contents"] || []
@@ -19,7 +20,7 @@ module Alchemy
19
20
 
20
21
  conditional_template "editor.html.#{template_engine}", "#{elements_dir}/_#{@element_name}_editor.html.#{template_engine}"
21
22
  conditional_template "view.html.#{template_engine}", "#{elements_dir}/_#{@element_name}_view.html.#{template_engine}"
22
- end if @elements
23
+ end
23
24
  end
24
25
 
25
26
  private
@@ -8,11 +8,12 @@ module Alchemy
8
8
 
9
9
  def create_partials
10
10
  @page_layouts = load_alchemy_yaml('page_layouts.yml')
11
+ return unless @page_layouts
11
12
  @page_layouts.each do |page_layout|
12
13
  next if page_layout['redirects_to_external']
13
14
  @page_layout_name = page_layout["name"].underscore
14
15
  conditional_template "layout.html.#{template_engine}", "#{page_layouts_dir}/_#{@page_layout_name}.html.#{template_engine}"
15
- end if @page_layouts
16
+ end
16
17
  end
17
18
 
18
19
  private
@@ -8,10 +8,11 @@ module Alchemy
8
8
 
9
9
  def create_partials
10
10
  @sites = Alchemy::Site.all
11
+ return unless @sites
11
12
  @sites.each do |site|
12
13
  @site_name = site.name.parameterize.underscore
13
14
  conditional_template "layout.html.#{template_engine}", "#{site_layouts_dir}/_#{@site_name}.html.#{template_engine}"
14
- end if @sites
15
+ end
15
16
  end
16
17
 
17
18
  private
@@ -63,123 +63,125 @@ module Alchemy
63
63
  class Tidy
64
64
  extend Shell
65
65
 
66
- def self.create_missing_cells(page_layouts, cells)
67
- page_layouts.each do |layout|
68
- next if layout['cells'].blank?
69
- cells_for_layout = cells.select { |cell| layout['cells'].include? cell['name'] }
70
- Alchemy::Page.where(page_layout: layout['name']).each do |page|
71
- cells_for_layout.each do |cell_for_layout|
72
- cell = Alchemy::Cell.find_or_initialize_by(name: cell_for_layout['name'], page_id: page.id)
73
- cell.elements << page.elements.select { |element| cell_for_layout['elements'].include?(element.name) }
74
- if cell.new_record?
75
- cell.save
76
- log "Creating cell #{cell.name} for page #{page.name}"
77
- else
78
- log "Cell #{cell.name} for page #{page.name} already present", :skip
66
+ class << self
67
+ def create_missing_cells(page_layouts, cells)
68
+ page_layouts.each do |layout|
69
+ next if layout['cells'].blank?
70
+ cells_for_layout = cells.select { |cell| layout['cells'].include? cell['name'] }
71
+ Alchemy::Page.where(page_layout: layout['name']).each do |page|
72
+ cells_for_layout.each do |cell_for_layout|
73
+ cell = Alchemy::Cell.find_or_initialize_by(name: cell_for_layout['name'], page_id: page.id)
74
+ cell.elements << page.elements.select { |element| cell_for_layout['elements'].include?(element.name) }
75
+ if cell.new_record?
76
+ cell.save
77
+ log "Creating cell #{cell.name} for page #{page.name}"
78
+ else
79
+ log "Cell #{cell.name} for page #{page.name} already present", :skip
80
+ end
79
81
  end
80
82
  end
81
83
  end
82
84
  end
83
- end
84
85
 
85
- def self.update_element_positions
86
- Alchemy::Page.all.each do |page|
87
- if page.elements.any?
88
- puts "\n## Updating element positions of page `#{page.name}`"
89
- end
90
- page.elements.group_by(&:cell_id).each do |_cell_id, elements|
91
- elements.each_with_index do |element, idx|
92
- position = idx + 1
93
- if element.position != position
94
- log "Updating position for element ##{element.id} to #{position}"
95
- element.update_column(:position, position)
96
- else
97
- log "Position for element ##{element.id} is already correct (#{position})", :skip
86
+ def update_element_positions
87
+ Alchemy::Page.all.each do |page|
88
+ if page.elements.any?
89
+ puts "\n## Updating element positions of page `#{page.name}`"
90
+ end
91
+ page.elements.group_by(&:cell_id).each do |_cell_id, elements|
92
+ elements.each_with_index do |element, idx|
93
+ position = idx + 1
94
+ if element.position != position
95
+ log "Updating position for element ##{element.id} to #{position}"
96
+ element.update_column(:position, position)
97
+ else
98
+ log "Position for element ##{element.id} is already correct (#{position})", :skip
99
+ end
98
100
  end
99
101
  end
100
102
  end
101
103
  end
102
- end
103
104
 
104
- def self.update_content_positions
105
- Alchemy::Element.all.each do |element|
106
- if element.contents.any?
107
- puts "\n## Updating content positions of element `#{element.name}`"
108
- end
109
- element.contents.group_by(&:essence_type).each do |essence_type, contents|
110
- puts "-> Contents of type `#{essence_type}`"
111
- contents.each_with_index do |content, idx|
112
- position = idx + 1
113
- if content.position != position
114
- log "Updating position for content ##{content.id} to #{position}"
115
- content.update_column(:position, position)
116
- else
117
- log "Position for content ##{content.id} is already correct (#{position})", :skip
105
+ def update_content_positions
106
+ Alchemy::Element.all.each do |element|
107
+ if element.contents.any?
108
+ puts "\n## Updating content positions of element `#{element.name}`"
109
+ end
110
+ element.contents.group_by(&:essence_type).each do |essence_type, contents|
111
+ puts "-> Contents of type `#{essence_type}`"
112
+ contents.each_with_index do |content, idx|
113
+ position = idx + 1
114
+ if content.position != position
115
+ log "Updating position for content ##{content.id} to #{position}"
116
+ content.update_column(:position, position)
117
+ else
118
+ log "Position for content ##{content.id} is already correct (#{position})", :skip
119
+ end
118
120
  end
119
121
  end
120
122
  end
121
123
  end
122
- end
123
124
 
124
- def self.remove_orphaned_cells
125
- puts "\n## Removing orphaned cells"
126
- cells = Alchemy::Cell.unscoped.all
127
- if cells.any?
128
- orphaned_cells = cells.select do |cell|
129
- cell.page.nil? && cell.page_id.present?
130
- end
131
- if orphaned_cells.any?
132
- destroy_orphaned_records(orphaned_cells, 'cell')
125
+ def remove_orphaned_cells
126
+ puts "\n## Removing orphaned cells"
127
+ cells = Alchemy::Cell.unscoped.all
128
+ if cells.any?
129
+ orphaned_cells = cells.select do |cell|
130
+ cell.page.nil? && cell.page_id.present?
131
+ end
132
+ if orphaned_cells.any?
133
+ destroy_orphaned_records(orphaned_cells, 'cell')
134
+ else
135
+ log "No orphaned cells found", :skip
136
+ end
133
137
  else
134
- log "No orphaned cells found", :skip
138
+ log "No cells found", :skip
135
139
  end
136
- else
137
- log "No cells found", :skip
138
140
  end
139
- end
140
141
 
141
- def self.remove_orphaned_elements
142
- puts "\n## Removing orphaned elements"
143
- elements = Alchemy::Element.unscoped.all
144
- if elements.any?
145
- orphaned_elements = elements.select do |element|
146
- element.page.nil? && element.page_id.present? ||
147
- element.cell.nil? && element.cell_id.present?
148
- end
149
- if orphaned_elements.any?
150
- destroy_orphaned_records(orphaned_elements, 'element')
142
+ def remove_orphaned_elements
143
+ puts "\n## Removing orphaned elements"
144
+ elements = Alchemy::Element.unscoped.all
145
+ if elements.any?
146
+ orphaned_elements = elements.select do |element|
147
+ element.page.nil? && element.page_id.present? ||
148
+ element.cell.nil? && element.cell_id.present?
149
+ end
150
+ if orphaned_elements.any?
151
+ destroy_orphaned_records(orphaned_elements, 'element')
152
+ else
153
+ log "No orphaned elements found", :skip
154
+ end
151
155
  else
152
- log "No orphaned elements found", :skip
156
+ log "No elements found", :skip
153
157
  end
154
- else
155
- log "No elements found", :skip
156
158
  end
157
- end
158
159
 
159
- def self.remove_orphaned_contents
160
- puts "\n## Removing orphaned contents"
161
- contents = Alchemy::Content.unscoped.all
162
- if contents.any?
163
- orphaned_contents = contents.select do |content|
164
- content.essence.nil? && content.essence_id.present? ||
165
- content.element.nil? && content.element_id.present?
166
- end
167
- if orphaned_contents.any?
168
- destroy_orphaned_records(orphaned_contents, 'content')
160
+ def remove_orphaned_contents
161
+ puts "\n## Removing orphaned contents"
162
+ contents = Alchemy::Content.unscoped.all
163
+ if contents.any?
164
+ orphaned_contents = contents.select do |content|
165
+ content.essence.nil? && content.essence_id.present? ||
166
+ content.element.nil? && content.element_id.present?
167
+ end
168
+ if orphaned_contents.any?
169
+ destroy_orphaned_records(orphaned_contents, 'content')
170
+ else
171
+ log "No orphaned contents found", :skip
172
+ end
169
173
  else
170
- log "No orphaned contents found", :skip
174
+ log "No contents found", :skip
171
175
  end
172
- else
173
- log "No contents found", :skip
174
176
  end
175
- end
176
177
 
177
- private
178
+ private
178
179
 
179
- def self.destroy_orphaned_records(records, class_name)
180
- records.each do |record|
181
- log "Destroy orphaned #{class_name}: #{record.id}"
182
- record.destroy
180
+ def destroy_orphaned_records(records, class_name)
181
+ records.each do |record|
182
+ log "Destroy orphaned #{class_name}: #{record.id}"
183
+ record.destroy
184
+ end
183
185
  end
184
186
  end
185
187
  end