Skip to content

Commit

Permalink
Fix constants reloading in page and element concerns
Browse files Browse the repository at this point in the history
The classes must not be redefined as modules. Also require the dependency
to that Rails autoloader is able to find the concerns.
  • Loading branch information
tvdeyen committed Feb 15, 2021
1 parent 84c9d30 commit d983b25
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 d983b25

Please sign in to comment.