Skip to content

Commit

Permalink
Merge pull request #2024 from tvdeyen/fix-autoloading
Browse files Browse the repository at this point in the history
Fix constants reloading in page and element concerns
  • Loading branch information
tvdeyen authored Feb 15, 2021
2 parents 84c9d30 + d983b25 commit 4e7d035
Show file tree
Hide file tree
Showing 11 changed files with 908 additions and 879 deletions.
13 changes: 9 additions & 4 deletions app/models/alchemy/element.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
# parent_element_id :integer
#

require_dependency "alchemy/element/definitions"
require_dependency "alchemy/element/element_contents"
require_dependency "alchemy/element/element_essences"
require_dependency "alchemy/element/presenters"

module Alchemy
class Element < BaseRecord
NAME_REGEXP = /\A[a-z0-9_-]+\z/
Expand Down Expand Up @@ -117,10 +122,10 @@ class Element < BaseRecord
delegate :restricted?, to: :page, allow_nil: true

# Concerns
include Alchemy::Element::Definitions
include Alchemy::Element::ElementContents
include Alchemy::Element::ElementEssences
include Alchemy::Element::Presenters
include Definitions
include ElementContents
include ElementEssences
include Presenters

# class methods
class << self
Expand Down
56 changes: 29 additions & 27 deletions app/models/alchemy/element/definitions.rb
Original file line number Diff line number Diff line change
@@ -1,37 +1,39 @@
# frozen_string_literal: true

module Alchemy
# Module concerning element definitions
#
module Element::Definitions
extend ActiveSupport::Concern
class Element < BaseRecord
# Module concerning element definitions
#
module Definitions
extend ActiveSupport::Concern

module ClassMethods
# Returns the definitions from elements.yml file.
#
# Place a +elements.yml+ file inside your apps +config/alchemy+ folder to define
# your own set of elements
#
def definitions
ElementDefinition.all
end
module ClassMethods
# Returns the definitions from elements.yml file.
#
# Place a +elements.yml+ file inside your apps +config/alchemy+ folder to define
# your own set of elements
#
def definitions
ElementDefinition.all
end

# Returns one element definition by given name.
#
def definition_by_name(name)
ElementDefinition.get(name)
# Returns one element definition by given name.
#
def definition_by_name(name)
ElementDefinition.get(name)
end
end
end

# The definition of this element.
#
def definition
if definition = self.class.definition_by_name(name)
definition
else
log_warning "Could not find element definition for #{name}. " \
"Please check your elements.yml file!"
{}
# The definition of this element.
#
def definition
if definition = self.class.definition_by_name(name)
definition
else
log_warning "Could not find element definition for #{name}. " \
"Please check your elements.yml file!"
{}
end
end
end
end
Expand Down
250 changes: 126 additions & 124 deletions app/models/alchemy/element/element_contents.rb
Original file line number Diff line number Diff line change
@@ -1,151 +1,153 @@
# frozen_string_literal: true

# Methods concerning contents for elements
#
module Alchemy
module Element::ElementContents
# Find first content from element by given name.
def content_by_name(name)
contents_by_name(name).first
end

# Find first content from element by given essence type.
def content_by_type(essence_type)
contents_by_type(essence_type).first
end

# All contents from element by given name.
def contents_by_name(name)
contents.select { |content| content.name == name.to_s }
end
alias_method :all_contents_by_name, :contents_by_name
class Element < BaseRecord
# Methods concerning contents for elements
#
module ElementContents
# Find first content from element by given name.
def content_by_name(name)
contents_by_name(name).first
end

# All contents from element by given essence type.
def contents_by_type(essence_type)
contents.select do |content|
content.essence_type == Content.normalize_essence_type(essence_type)
# Find first content from element by given essence type.
def content_by_type(essence_type)
contents_by_type(essence_type).first
end
end
alias_method :all_contents_by_type, :contents_by_type

# Updates all related contents by calling +update_essence+ on each of them.
#
# @param contents_attributes [Hash]
# Hash of contents attributes.
# The keys has to be the #id of the content to update.
# The values a Hash of attribute names and values
#
# @return [Boolean]
# True if +errors+ are blank or +contents_attributes+ hash is nil
#
# == Example
#
# @element.update_contents(
# "1" => {ingredient: "Title"},
# "2" => {link: "https://google.com"}
# )
#
def update_contents(contents_attributes)
return true if contents_attributes.nil?
# All contents from element by given name.
def contents_by_name(name)
contents.select { |content| content.name == name.to_s }
end
alias_method :all_contents_by_name, :contents_by_name

contents.each do |content|
content_hash = contents_attributes[content.id.to_s] || next
content.update_essence(content_hash) || errors.add(:base, :essence_validation_failed)
# All contents from element by given essence type.
def contents_by_type(essence_type)
contents.select do |content|
content.essence_type == Content.normalize_essence_type(essence_type)
end
end
alias_method :all_contents_by_type, :contents_by_type

# Updates all related contents by calling +update_essence+ on each of them.
#
# @param contents_attributes [Hash]
# Hash of contents attributes.
# The keys has to be the #id of the content to update.
# The values a Hash of attribute names and values
#
# @return [Boolean]
# True if +errors+ are blank or +contents_attributes+ hash is nil
#
# == Example
#
# @element.update_contents(
# "1" => {ingredient: "Title"},
# "2" => {link: "https://google.com"}
# )
#
def update_contents(contents_attributes)
return true if contents_attributes.nil?

contents.each do |content|
content_hash = contents_attributes[content.id.to_s] || next
content.update_essence(content_hash) || errors.add(:base, :essence_validation_failed)
end
errors.blank?
end
errors.blank?
end

# Copy current content's contents to given target element
def copy_contents_to(element)
contents.map do |content|
Content.copy(content, element_id: element.id)
# Copy current content's contents to given target element
def copy_contents_to(element)
contents.map do |content|
Content.copy(content, element_id: element.id)
end
end
end

# Returns the content that is marked as rss title.
#
# Mark a content as rss title in your +elements.yml+ file:
#
# - name: news
# contents:
# - name: headline
# type: EssenceText
# rss_title: true
#
def content_for_rss_title
content_for_rss_meta("title")
end
# Returns the content that is marked as rss title.
#
# Mark a content as rss title in your +elements.yml+ file:
#
# - name: news
# contents:
# - name: headline
# type: EssenceText
# rss_title: true
#
def content_for_rss_title
content_for_rss_meta("title")
end

# Returns the content that is marked as rss description.
#
# Mark a content as rss description in your +elements.yml+ file:
#
# - name: news
# contents:
# - name: body
# type: EssenceRichtext
# rss_description: true
#
def content_for_rss_description
content_for_rss_meta("description")
end
# Returns the content that is marked as rss description.
#
# Mark a content as rss description in your +elements.yml+ file:
#
# - name: news
# contents:
# - name: body
# type: EssenceRichtext
# rss_description: true
#
def content_for_rss_description
content_for_rss_meta("description")
end

# Returns the array with the hashes for all element contents in the elements.yml file
def content_definitions
return nil if definition.blank?
# Returns the array with the hashes for all element contents in the elements.yml file
def content_definitions
return nil if definition.blank?

definition["contents"]
end
definition["contents"]
end

# Returns the definition for given content_name
def content_definition_for(content_name)
if content_definitions.blank?
log_warning "Element #{name} is missing the content definition for #{content_name}"
nil
else
content_definitions.detect { |d| d["name"] == content_name.to_s }
# Returns the definition for given content_name
def content_definition_for(content_name)
if content_definitions.blank?
log_warning "Element #{name} is missing the content definition for #{content_name}"
nil
else
content_definitions.detect { |d| d["name"] == content_name.to_s }
end
end
end

# Returns an array of all EssenceRichtext contents ids from elements
#
# This is used to re-initialize the TinyMCE editor in the element editor.
#
def richtext_contents_ids
# This is not very efficient SQL wise I know, but we need to iterate
# recursivly through all descendent elements and I don't know how to do this
# in pure SQL. Anyone with a better idea is welcome to submit a patch.
ids = contents.select(&:has_tinymce?).collect(&:id)
expanded_nested_elements = nested_elements.expanded
if expanded_nested_elements.present?
ids += expanded_nested_elements.collect(&:richtext_contents_ids)
# Returns an array of all EssenceRichtext contents ids from elements
#
# This is used to re-initialize the TinyMCE editor in the element editor.
#
def richtext_contents_ids
# This is not very efficient SQL wise I know, but we need to iterate
# recursivly through all descendent elements and I don't know how to do this
# in pure SQL. Anyone with a better idea is welcome to submit a patch.
ids = contents.select(&:has_tinymce?).collect(&:id)
expanded_nested_elements = nested_elements.expanded
if expanded_nested_elements.present?
ids += expanded_nested_elements.collect(&:richtext_contents_ids)
end
ids.flatten
end
ids.flatten
end

# True, if any of the element's contents has essence validations defined.
def has_validations?
!contents.detect(&:has_validations?).blank?
end
# True, if any of the element's contents has essence validations defined.
def has_validations?
!contents.detect(&:has_validations?).blank?
end

# All element contents where the essence validation has failed.
def contents_with_errors
contents.select(&:essence_validation_failed?)
end
# All element contents where the essence validation has failed.
def contents_with_errors
contents.select(&:essence_validation_failed?)
end

private
private

def content_for_rss_meta(type)
definition = content_definitions.detect { |c| c["rss_#{type}"] }
return if definition.blank?
def content_for_rss_meta(type)
definition = content_definitions.detect { |c| c["rss_#{type}"] }
return if definition.blank?

contents.detect { |content| content.name == definition["name"] }
end
contents.detect { |content| content.name == definition["name"] }
end

# creates the contents for this element as described in the elements.yml
def create_contents
definition.fetch("contents", []).each do |attributes|
Content.create(attributes.merge(element: self))
# creates the contents for this element as described in the elements.yml
def create_contents
definition.fetch("contents", []).each do |attributes|
Content.create(attributes.merge(element: self))
end
end
end
end
Expand Down
Loading

0 comments on commit 4e7d035

Please sign in to comment.