alchemy_cms 3.5.0 → 3.6.0

Sign up to get free protection for your applications and to get access to all the features.
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