engine/app/models/extensions/page/editable_elements.rb

115 lines
3.8 KiB
Ruby
Raw Normal View History

module Models
module Extensions
module Page
module EditableElements
extend ActiveSupport::Concern
included do
embeds_many :editable_elements
after_save :remove_disabled_editable_elements
# editable file callbacks
after_save :store_file_sources!
before_save :write_file_source_identifiers
after_destroy :remove_file_sources!
accepts_nested_attributes_for :editable_elements
end
module InstanceMethods
def disable_parent_editable_elements(block)
self.editable_elements.each { |el| el.disabled = true if el.from_parent? && el.block == block }
end
def disable_all_editable_elements
self.editable_elements.each { |el| el.disabled = true }
end
def editable_element_blocks
self.editable_elements.collect(&:block)
end
def editable_elements_grouped_by_blocks
all_enabled = self.editable_elements.reject { |el| el.disabled? }
groups = all_enabled.group_by(&:block)
groups.delete_if { |block, elements| elements.empty? }
end
def find_editable_element(block, slug)
self.editable_elements.detect { |el| el.block == block && el.slug == slug }
end
def find_editable_files
self.editable_elements.find_all { |el| el.respond_to?(:source) }
end
def add_or_update_editable_element(attributes, type)
element = self.find_editable_element(attributes[:block], attributes[:slug])
if element
element.attributes = attributes
else
self.editable_elements.build(attributes, type)
end
end
def enable_editable_elements(block)
self.editable_elements.each { |el| el.disabled = false if el.block == block }
end
def merge_editable_elements_from_page(source)
source.editable_elements.each do |el|
next if el.disabled? or !el.assignable?
existing_el = self.find_editable_element(el.block, el.slug)
if existing_el.nil? # new one from parents
new_attributes = el.attributes.merge(:from_parent => true)
if new_attributes['default_attribute'].present?
new_attributes['default_content'] = self.send(new_attributes['default_attribute']) || el.content
else
new_attributes['default_content'] = el.content
end
self.editable_elements.build(new_attributes, el.class)
else
existing_el.attributes = { :disabled => false, :default_content => el.content }
end
end
end
def remove_disabled_editable_elements
return unless self.editable_elements.any? { |el| el.disabled? }
# super fast way to remove useless elements all in once (TODO callbacks)
self.collection.update(self._selector, '$pull' => { 'editable_elements' => { 'disabled' => true } })
end
protected
## callbacks for editable files
# equivalent to "after_save :store_source!" in EditableFile
def store_file_sources!
self.find_editable_files.collect(&:store_source!)
end
# equivalent to "before_save :write_source_identifier" in EditableFile
def write_file_source_identifiers
self.find_editable_files.collect(&:write_source_identifier)
end
# equivalent to "after_destroy :remove_source!" in EditableFile
def remove_file_sources!
self.find_editable_files.collect(&:remove_source!)
end
end
end
end
end
end