Class: Alchemy::Element

Inherits:
BaseRecord
  • Object
show all
Includes:
Definitions, ElementContents, ElementEssences, Presenters, Hints, Logger, Taggable
Defined in:
app/models/alchemy/element.rb

Defined Under Namespace

Modules: Definitions, ElementContents, ElementEssences, Presenters

Constant Summary collapse

FORBIDDEN_DEFINITION_ATTRIBUTES =
[
  "amount",
  "nestable_elements",
  "contents",
  "hint",
  "picture_gallery",
  "taggable"
].freeze
SKIPPED_ATTRIBUTES_ON_COPY =
[
  "cached_tag_list",
  "created_at",
  "creator_id",
  "id",
  "folded",
  "position",
  "updated_at",
  "updater_id"
].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Presenters

#display_name, #display_name_with_preview_text, #dom_id, #preview_content, #preview_text

Methods included from ElementEssences

#essence_error_messages, #essence_errors, #has_ingredient?, #ingredient

Methods included from ElementContents

#content_by_name, #content_by_type, #content_definition_for, #content_definitions, #content_for_rss_description, #content_for_rss_title, #contents_by_name, #contents_by_type, #contents_with_errors, #copy_contents_to, #has_validations?, #richtext_contents_ids, #update_contents

Methods included from Definitions

#definition

Methods included from Hints

#has_hint?, #hint

Methods included from Taggable

included, #tag_list=

Methods included from Logger

#log_warning, warn

Methods inherited from BaseRecord

#active_record_5_1?

Instance Attribute Details

#create_contents_after_createObject

Returns the value of attribute create_contents_after_create.



88
89
90
# File 'app/models/alchemy/element.rb', line 88

def create_contents_after_create
  @create_contents_after_create
end

Class Method Details

.all_from_clipboard(clipboard) ⇒ Object



175
176
177
178
# File 'app/models/alchemy/element.rb', line 175

def all_from_clipboard(clipboard)
  return [] if clipboard.nil?
  where(id: clipboard.collect { |e| e['id'] })
end

.all_from_clipboard_for_page(clipboard, page) ⇒ Object

All elements in clipboard that could be placed on page



182
183
184
185
186
187
# File 'app/models/alchemy/element.rb', line 182

def all_from_clipboard_for_page(clipboard, page)
  return [] if clipboard.nil? || page.nil?
  all_from_clipboard(clipboard).select { |ce|
    page.available_element_names.include?(ce.name)
  }
end

.copy(source_element, differences = {}) ⇒ Object

This methods does a copy of source and all depending contents and all of their depending essences.

Options

You can pass a differences Hash as second option to update attributes for the copy.

Example

@copy = Alchemy::Element.copy(@element, {public: false})
@copy.public? # => false


153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'app/models/alchemy/element.rb', line 153

def copy(source_element, differences = {})
  attributes = source_element.attributes.with_indifferent_access
                 .except(*SKIPPED_ATTRIBUTES_ON_COPY)
                 .merge(differences)
                 .merge({
                   create_contents_after_create: false,
                   tag_list: source_element.tag_list
                 })

  new_element = create!(attributes)

  if source_element.contents.any?
    source_element.copy_contents_to(new_element)
  end

  if source_element.nested_elements.any?
    source_element.copy_nested_elements_to(new_element)
  end

  new_element
end

.create_from_scratch(attributes) ⇒ Object

Creates a new element as described in /config/alchemy/elements.yml

  • Returns a new Alchemy::Element object if no name is given in attributes, because the definition can not be found w/o name

  • Raises Alchemy::ElementDefinitionError if no definition for given attributes could be found



136
137
138
139
140
# File 'app/models/alchemy/element.rb', line 136

def create_from_scratch(attributes)
  element = new_from_scratch(attributes)
  element.save if element
  element
end

.new_from_scratch(attributes = {}) ⇒ Object

Builds a new element as described in /config/alchemy/elements.yml

  • Returns a new Alchemy::Element object if no name is given in attributes, because the definition can not be found w/o name

  • Raises Alchemy::ElementDefinitionError if no definition for given attributes could be found



124
125
126
127
# File 'app/models/alchemy/element.rb', line 124

def new_from_scratch(attributes = {})
  return new if attributes[:name].blank?
  new_element_from_definition_by(attributes) || raise(ElementDefinitionError, attributes)
end

Instance Method Details

#available_page_cell_names(page) ⇒ Object

The names of all cells from given page this element could be placed in.



240
241
242
243
244
245
246
247
# File 'app/models/alchemy/element.rb', line 240

def available_page_cell_names(page)
  cellnames = unique_available_page_cell_names(page)
  if cellnames.blank? || !page.has_cells?
    ['for_other_elements']
  else
    cellnames
  end
end

#cache_keyObject

Returns the key that’s taken for cache path.

Uses the page’s published_at value that’s updated when the user publishes the page.

If the page is the current preview it uses the element’s updated_at value as cache key.



283
284
285
286
287
288
289
# File 'app/models/alchemy/element.rb', line 283

def cache_key
  if Page.current_preview == page
    "alchemy/elements/#{id}-#{updated_at}"
  else
    "alchemy/elements/#{id}-#{page.published_at}"
  end
end

#copy_nested_elements_to(target_element) ⇒ Object

Copy all nested elements from current element to given target element.



297
298
299
300
301
302
303
304
305
# File 'app/models/alchemy/element.rb', line 297

def copy_nested_elements_to(target_element)
  nested_elements.map do |nested_element|
    Element.copy(nested_element, {
      parent_element_id: target_element.id,
      page_id: target_element.page_id,
      cell_id: target_element.cell_id
    })
  end
end

#expanded?Boolean

The opposite of folded?

Returns:

  • (Boolean)


255
256
257
# File 'app/models/alchemy/element.rb', line 255

def expanded?
  !folded?
end

#nestable_elementsObject

A collection of element names that can be nested inside this element.



292
293
294
# File 'app/models/alchemy/element.rb', line 292

def nestable_elements
  definition.fetch('nestable_elements', [])
end

#next(name = nil) ⇒ Object

Returns next public element from same page.

Pass an element name to get next of this kind.



204
205
206
207
# File 'app/models/alchemy/element.rb', line 204

def next(name = nil)
  elements = page.elements.published.where('position > ?', position)
  select_element(elements, name, :asc)
end

#prev(name = nil) ⇒ Object

Returns previous public element from same page.

Pass an element name to get previous of this kind.



213
214
215
216
# File 'app/models/alchemy/element.rb', line 213

def prev(name = nil)
  elements = page.elements.published.where('position < ?', position)
  select_element(elements, name, :desc)
end

#store_page(page) ⇒ Object

Stores the page into touchable_pages (Pages that have to be touched after updating the element).



219
220
221
222
223
224
225
# File 'app/models/alchemy/element.rb', line 219

def store_page(page)
  return true if page.nil?
  unless touchable_pages.include? page
    touchable_pages << page
    save
  end
end

#taggable?Boolean

Returns true if the definition of this element has a taggable true value.

Returns:

  • (Boolean)


250
251
252
# File 'app/models/alchemy/element.rb', line 250

def taggable?
  definition['taggable'] == true
end

#to_partial_pathObject

The element’s view partial is dependent from its name

Define elements

Elements are defined in the config/alchemy/elements.yml file

- name: article
  contents:
  ...

Override the view

Element partials live in app/views/alchemy/elements



273
274
275
# File 'app/models/alchemy/element.rb', line 273

def to_partial_path
  "alchemy/elements/#{name}_view"
end

#trash!Object

Trashing an element means nullifying its position, folding and unpublishing it.



228
229
230
231
232
# File 'app/models/alchemy/element.rb', line 228

def trash!
  self.public = false
  self.folded = true
  remove_from_list
end

#trashed?Boolean

Returns:

  • (Boolean)


234
235
236
# File 'app/models/alchemy/element.rb', line 234

def trashed?
  position.nil?
end