Class: Alchemy::Page
- Inherits:
 - 
      BaseRecord
      
        
- Object
 - ActiveRecord::Base
 - BaseRecord
 - Alchemy::Page
 
 
- Includes:
 - Hints, Logger, PageElements, PageLayouts, PageNaming, PageNatures, PageScopes, Taggable
 
- Defined in:
 - app/models/alchemy/page/page_scopes.rb,
app/models/alchemy/page.rb,
app/models/alchemy/page/url_path.rb,
app/models/alchemy/page/publisher.rb,
app/models/alchemy/page/page_naming.rb,
app/models/alchemy/page/page_layouts.rb,
app/models/alchemy/page/page_natures.rb,
app/models/alchemy/page/page_elements.rb,
app/models/alchemy/page/fixed_attributes.rb 
Overview
ActiveRecord scopes for Alchemy::Page
Defined Under Namespace
Modules: PageElements, PageLayouts, PageNaming, PageNatures, PageScopes Classes: FixedAttributes, Publisher, UrlPath
Constant Summary collapse
- DEFAULT_ATTRIBUTES_FOR_COPY =
 { autogenerate_elements: false, public_on: nil, public_until: nil, locked_at: nil, locked_by: nil }
- SKIPPED_ATTRIBUTES_ON_COPY =
 %w[ id updated_at created_at creator_id updater_id lft rgt depth urlname cached_tag_list ]
- PERMITTED_ATTRIBUTES =
 [ :meta_description, :meta_keywords, :name, :page_layout, :public_on, :public_until, :restricted, :robot_index, :robot_follow, :searchable, :sitemap, :tag_list, :title, :urlname, :layoutpage, :menu_id ]
Constants included from PageNaming
Constants included from SearchableResource
SearchableResource::SEARCHABLE_COLUMN_TYPES
Class Method Summary collapse
- .alchemy_resource_filters ⇒ Object
 - .all_from_clipboard(clipboard) ⇒ Object
 - .all_from_clipboard_for_select(clipboard, language_id, layoutpages: false) ⇒ Object
 - 
  
    
      .copy(source, differences = {})  ⇒ Alchemy::Page 
    
    
  
  
  
  
  
  
  
  
  
    
Creates a copy of given source.
 - .copy_and_paste(source, new_parent, new_name) ⇒ Object
 - 
  
    
      .current_preview  ⇒ Object 
    
    
  
  
  
  
  
  
  deprecated
  
  
    Deprecated. 
Use Current#preview_page instead.
 - 
  
    
      .current_preview=(page)  ⇒ Object 
    
    
  
  
  
  
  
  
  deprecated
  
  
    Deprecated. 
Use Current#preview_page= instead.
 - 
  
    
      .language_root_for(language_id)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
The language root page for given language id.
 - .link_target_options ⇒ Object
 - .searchable_alchemy_resource_attributes ⇒ Object
 - 
  
    
      .url_path_class  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
The url_path class.
 - 
  
    
      .url_path_class=(klass)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Set a custom url path class.
 
Instance Method Summary collapse
- 
  
    
      #attribute_fixed?(name)  ⇒ Boolean 
    
    
  
  
  
  
  
  
  
  
  
    
True if given attribute name is defined as fixed.
 - #copy_children_to(new_parent) ⇒ Object
 - 
  
    
      #creator_name  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Returns the name of the creator of this page.
 - 
  
    
      #editable_by?(user)  ⇒ Boolean 
    
    
  
  
  
  
  
  
  
  
  
    
Checks the current page’s list of editors, if defined.
 - 
  
    
      #find_elements(options = {})  ⇒ ActiveRecord::Relation 
    
    
  
  
  
  
  
  
  
  
  
    
Returns elements from pages public version.
 - 
  
    
      #first_public_child  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Returns the first published child.
 - 
  
    
      #fixed_attributes  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Holds an instance of
FixedAttributes. - #fold!(user_id, status) ⇒ Object
 - 
  
    
      #get_language_root  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Gets the language_root page for page.
 - 
  
    
      #hint_translation_attribute  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Key hint translations by page layout, rather than the default name.
 - #inherit_restricted_status ⇒ Object
 - 
  
    
      #lock_to!(user)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Locks the page to given user.
 - 
  
    
      #locker_name  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Returns the name of the user currently editing this page.
 - 
  
    
      #menus  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Menus (aka. root nodes) this page is attached to.
 - 
  
    
      #next(options = {})  ⇒ Object 
    
    
      (also: #next_page)
    
  
  
  
  
  
  
  
  
  
    
Returns the next page on the same level or nil.
 - 
  
    
      #previous(options = {})  ⇒ Object 
    
    
      (also: #previous_page)
    
  
  
  
  
  
  
  
  
  
    
Returns the previous page on the same level or nil.
 - 
  
    
      #public_on  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Returns the value of
public_onattribute from public version. - 
  
    
      #public_on=(time)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Sets the public_on date on the published version.
 - 
  
    
      #public_until  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Returns the value of
public_untilattribute. - 
  
    
      #publish!(current_time = Time.current)  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Creates a public version of the page in the background.
 - #set_restrictions_to_child_pages ⇒ Object
 - 
  
    
      #to_partial_path  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
The page’s view partial is dependent from its page layout.
 - 
  
    
      #unlock!  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Unlocks the page without updating the timestamps.
 - 
  
    
      #updater_name  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
Returns the name of the last updater of this page.
 - 
  
    
      #url_path  ⇒ Object 
    
    
  
  
  
  
  
  
  
  
  
    
The url_path for this page.
 
Methods included from PageElements
#available_element_definitions, #available_element_names, #available_elements_within_current_scope, #descendent_element_definitions, #element_definition_names, #element_definitions, #element_definitions_by_name, #richtext_ingredients_ids
Methods included from PageNaming
#renamed?, #slug, #update_urlname!
Methods included from NameConversions
#convert_to_humanized_name, #convert_to_urlname
Methods included from PageNatures
#cache_page?, #cache_version, #definition, #editor_roles, #expiration_time, #folded?, #has_limited_editors?, #last_modified_at, #layout_display_name, #layout_partial_name, #locked?, #public?, #rootpage?, #status, #status_message, #status_title
Methods included from Taggable
Methods included from Logger
Methods included from Hints
Methods included from SearchableResource
#ransackable_associations, #ransackable_attributes, #ransortable_attributes
Class Method Details
.alchemy_resource_filters ⇒ Object
      186 187 188 189 190 191 192 193 194 195 196 197  | 
    
      # File 'app/models/alchemy/page.rb', line 186 def alchemy_resource_filters [ { name: :by_page_layout, values: PageLayout.all.map { |p| [Alchemy.t(p["name"], scope: "page_layout_names"), p["name"]] } }, { name: :status, values: %w[published not_public restricted] } ] end  | 
  
.all_from_clipboard(clipboard) ⇒ Object
      257 258 259 260 261  | 
    
      # File 'app/models/alchemy/page.rb', line 257 def all_from_clipboard(clipboard) return [] if clipboard.blank? where(id: clipboard.collect { |p| p["id"] }) end  | 
  
.all_from_clipboard_for_select(clipboard, language_id, layoutpages: false) ⇒ Object
      263 264 265 266 267 268 269 270  | 
    
      # File 'app/models/alchemy/page.rb', line 263 def all_from_clipboard_for_select(clipboard, language_id, layoutpages: false) return [] if clipboard.blank? clipboard_pages = all_from_clipboard(clipboard) allowed_page_layouts = Alchemy::Page.selectable_layouts(language_id, layoutpages: layoutpages) allowed_page_layout_names = allowed_page_layouts.collect { |p| p["name"] } clipboard_pages.select { |cp| allowed_page_layout_names.include?(cp.page_layout) } end  | 
  
.copy(source, differences = {}) ⇒ Alchemy::Page
Creates a copy of given source.
Also copies all elements included in source.
Note:
It prevents the element auto generator from running.
      239 240 241  | 
    
      # File 'app/models/alchemy/page.rb', line 239 def copy(source, differences = {}) Alchemy::CopyPage.new(page: source).call(changed_attributes: differences) end  | 
  
.copy_and_paste(source, new_parent, new_name) ⇒ Object
      243 244 245 246 247 248 249 250 251 252 253 254 255  | 
    
      # File 'app/models/alchemy/page.rb', line 243 def copy_and_paste(source, new_parent, new_name) page = Alchemy::CopyPage.new(page: source) .call(changed_attributes: { parent: new_parent, language: new_parent&.language, name: new_name, title: new_name }) if source.children.any? source.copy_children_to(page) end page end  | 
  
.current_preview ⇒ Object
Use Current#preview_page instead.
Returns the current page previewed in the edit page template.
      212 213 214  | 
    
      # File 'app/models/alchemy/page.rb', line 212 def current_preview Current.preview_page end  | 
  
.current_preview=(page) ⇒ Object
Use Current#preview_page= instead.
Used to store the current page previewed in the edit page template.
      205 206 207  | 
    
      # File 'app/models/alchemy/page.rb', line 205 def current_preview=(page) Current.preview_page = page end  | 
  
.language_root_for(language_id) ⇒ Object
Returns the language root page for given language id.
      220 221 222  | 
    
      # File 'app/models/alchemy/page.rb', line 220 def language_root_for(language_id) language_roots.find_by_language_id(language_id) end  | 
  
.link_target_options ⇒ Object
      272 273 274 275 276 277 278 279 280 281 282  | 
    
      # File 'app/models/alchemy/page.rb', line 272 def = [[Alchemy.t(:default, scope: "link_target_options"), ""]] = Config.get(:link_target_options) .each do |option| # add an underscore to the options to provide the default syntax # @link https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#target << [Alchemy.t(option, scope: "link_target_options", default: option.to_s.humanize), "_#{option}"] end end  | 
  
.searchable_alchemy_resource_attributes ⇒ Object
      199 200 201  | 
    
      # File 'app/models/alchemy/page.rb', line 199 def searchable_alchemy_resource_attributes %w[name urlname title] end  | 
  
.url_path_class ⇒ Object
The url_path class
      173 174 175  | 
    
      # File 'app/models/alchemy/page.rb', line 173 def url_path_class @_url_path_class ||= Alchemy::Page::UrlPath end  | 
  
.url_path_class=(klass) ⇒ Object
Set a custom url path class
# config/initializers/alchemy.rb
Alchemy::Page.url_path_class = MyPageUrlPathClass
  
      182 183 184  | 
    
      # File 'app/models/alchemy/page.rb', line 182 def url_path_class=(klass) @_url_path_class = klass end  | 
  
Instance Method Details
#attribute_fixed?(name) ⇒ Boolean
True if given attribute name is defined as fixed
      457 458 459  | 
    
      # File 'app/models/alchemy/page.rb', line 457 def attribute_fixed?(name) fixed_attributes.fixed?(name) end  | 
  
#copy_children_to(new_parent) ⇒ Object
      412 413 414 415 416 417 418 419 420 421 422 423 424  | 
    
      # File 'app/models/alchemy/page.rb', line 412 def copy_children_to(new_parent) children.each do |child| next if child == new_parent new_child = Alchemy::CopyPage.new(page: child).call(changed_attributes: { parent_id: new_parent.id, language_id: new_parent.language_id, language_code: new_parent.language_code }) new_child.move_to_child_of(new_parent) child.copy_children_to(new_child) unless child.children.blank? end end  | 
  
#creator_name ⇒ Object
Returns the name of the creator of this page.
If no creator could be found or associated user model does not respond to #name it returns ‘unknown’
      493 494 495  | 
    
      # File 'app/models/alchemy/page.rb', line 493 def creator_name creator.try(:alchemy_display_name) || Alchemy.t("unknown") end  | 
  
#editable_by?(user) ⇒ Boolean
Checks the current page’s list of editors, if defined.
This allows us to pass in a user and see if any of their roles are enable them to make edits
      466 467 468 469 470  | 
    
      # File 'app/models/alchemy/page.rb', line 466 def editable_by?(user) return true unless has_limited_editors? (editor_roles & user.alchemy_roles).any? end  | 
  
#find_elements(options = {}) ⇒ ActiveRecord::Relation
Returns elements from pages public version.
You can pass another page_version to load elements from in the options.
      314 315 316 317  | 
    
      # File 'app/models/alchemy/page.rb', line 314 def find_elements( = {}) finder = [:finder] || Alchemy::ElementsFinder.new() finder.elements(page_version: [:page_version] || public_version) end  | 
  
#first_public_child ⇒ Object
Returns the first published child
      403 404 405  | 
    
      # File 'app/models/alchemy/page.rb', line 403 def first_public_child children.published.first end  | 
  
#fixed_attributes ⇒ Object
Holds an instance of FixedAttributes
      452 453 454  | 
    
      # File 'app/models/alchemy/page.rb', line 452 def fixed_attributes @_fixed_attributes ||= FixedAttributes.new(self) end  | 
  
#fold!(user_id, status) ⇒ Object
      386 387 388 389 390  | 
    
      # File 'app/models/alchemy/page.rb', line 386 def fold!(user_id, status) folded_page = folded_pages.find_or_create_by(user_id: user_id) folded_page.folded = status folded_page.save! end  | 
  
#get_language_root ⇒ Object
Gets the language_root page for page
      408 409 410  | 
    
      # File 'app/models/alchemy/page.rb', line 408 def get_language_root self_and_ancestors.find_by(language_root: true) end  | 
  
#hint_translation_attribute ⇒ Object
Key hint translations by page layout, rather than the default name.
      517 518 519  | 
    
      # File 'app/models/alchemy/page.rb', line 517 def hint_translation_attribute page_layout end  | 
  
#inherit_restricted_status ⇒ Object
      398 399 400  | 
    
      # File 'app/models/alchemy/page.rb', line 398 def inherit_restricted_status self.restricted = parent.restricted? end  | 
  
#lock_to!(user) ⇒ Object
Locks the page to given user
      374 375 376  | 
    
      # File 'app/models/alchemy/page.rb', line 374 def lock_to!(user) update_columns(locked_at: Time.current, locked_by: user.id) end  | 
  
#locker_name ⇒ Object
Returns the name of the user currently editing this page.
If no locker could be found or associated user model does not respond to #name it returns ‘unknown’
      511 512 513  | 
    
      # File 'app/models/alchemy/page.rb', line 511 def locker_name locker.try(:alchemy_display_name) || Alchemy.t("unknown") end  | 
  
#menus ⇒ Object
Menus (aka. root nodes) this page is attached to
      523 524 525  | 
    
      # File 'app/models/alchemy/page.rb', line 523 def @_menus ||= nodes.map(&:root) end  | 
  
#next(options = {}) ⇒ Object Also known as: next_page
Returns the next page on the same level or nil.
      365 366 367 368  | 
    
      # File 'app/models/alchemy/page.rb', line 365 def next( = {}) pages = self_and_siblings.where("lft > ?", lft) select_page(pages, .merge(order: :asc)) end  | 
  
#previous(options = {}) ⇒ Object Also known as: previous_page
Returns the previous page on the same level or nil.
      351 352 353 354  | 
    
      # File 'app/models/alchemy/page.rb', line 351 def previous( = {}) pages = self_and_siblings.where("lft < ?", lft) select_page(pages, .merge(order: :desc)) end  | 
  
#public_on ⇒ Object
Returns the value of public_on attribute from public version
If it’s a fixed attribute then the fixed value is returned instead
      476 477 478  | 
    
      # File 'app/models/alchemy/page.rb', line 476 def public_on attribute_fixed?(:public_on) ? fixed_attributes[:public_on] : public_version&.public_on end  | 
  
#public_on=(time) ⇒ Object
Sets the public_on date on the published version
Builds a new version if none exists yet. Destroys public version if empty time is set
      437 438 439 440 441 442 443 444 445 446 447  | 
    
      # File 'app/models/alchemy/page.rb', line 437 def public_on=(time) if public_version && time.blank? public_version.destroy! # Need to reset the public version on the instance so we do not need to reload self.public_version = nil elsif public_version public_version.public_on = time elsif time.present? versions.build(public_on: time) end end  | 
  
#public_until ⇒ Object
Returns the value of public_until attribute
If it’s a fixed attribute then the fixed value is returned instead
      484 485 486  | 
    
      # File 'app/models/alchemy/page.rb', line 484 def public_until attribute_fixed?(:public_until) ? fixed_attributes[:public_until] : public_version&.public_until end  | 
  
#publish!(current_time = Time.current) ⇒ Object
Creates a public version of the page in the background.
      428 429 430  | 
    
      # File 'app/models/alchemy/page.rb', line 428 def publish!(current_time = Time.current) PublishPageJob.perform_later(id, public_on: current_time) end  | 
  
#set_restrictions_to_child_pages ⇒ Object
      392 393 394 395 396  | 
    
      # File 'app/models/alchemy/page.rb', line 392 def set_restrictions_to_child_pages descendants.each do |child| child.update(restricted: restricted?) end end  | 
  
#to_partial_path ⇒ Object
The page’s view partial is dependent from its page layout
Define page layouts
Page layouts are defined in the config/alchemy/page_layouts.yml file
- name: contact
  elements: [contactform]
  ...
Override the view
Page layout partials live in app/views/alchemy/page_layouts
      340 341 342  | 
    
      # File 'app/models/alchemy/page.rb', line 340 def to_partial_path "alchemy/page_layouts/#{layout_partial_name}" end  | 
  
#unlock! ⇒ Object
Unlocks the page without updating the timestamps
      380 381 382 383 384  | 
    
      # File 'app/models/alchemy/page.rb', line 380 def unlock! if update_columns(locked_at: nil, locked_by: nil) Current.preview_page = nil end end  | 
  
#updater_name ⇒ Object
Returns the name of the last updater of this page.
If no updater could be found or associated user model does not respond to #name it returns ‘unknown’
      502 503 504  | 
    
      # File 'app/models/alchemy/page.rb', line 502 def updater_name updater.try(:alchemy_display_name) || Alchemy.t("unknown") end  | 
  
#url_path ⇒ Object
The url_path for this page
      322 323 324  | 
    
      # File 'app/models/alchemy/page.rb', line 322 def url_path self.class.url_path_class.new(self).call end  |