Class: Simplec::Page

Inherits:
ApplicationRecord show all
Defined in:
app/models/simplec/page.rb

Overview

This class represents a page in the system.

Model and Template Relationship.

Each page has a class located in:

app/models/page/NAME.rb

Each page has a partial template in:

app/views/pages/_NAME.html.erb

Where NAME is the demodulized, snake-case name of the Page Subclasss. For
example:

  class Page::Home < Page
    field :h1
  end

Would have a have a template in `app/views/pages/_home.html.erb`.

Defined Under Namespace

Classes: AlreadyLinkedEmbeddedImage

Constant Summary collapse

FILE_FIELDS =
[:file, :image].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#fieldsJSON

JSONB Postgres field that holds all defined fields. Use only if you know what you are doing.


# File 'app/models/simplec/page.rb', line 78

#layoutString

This is the layout to be used when the page is rendered. This attribute overrides the associated Subdomain's default_layout.

See Simplec::Subdomain#layouts to get a list of optional layouts.


# File 'app/models/simplec/page.rb', line 70

#meta_descriptionString

This is the meta description tag for the page.


# File 'app/models/simplec/page.rb', line 66

#pathString (readonly)

The the path is computed from the slug and the sum all parent pages.


# File 'app/models/simplec/page.rb', line 58

#slugString

The value is normalized to a string starting without a leading slash and ending without a slash. Case is not changed.


# File 'app/models/simplec/page.rb', line 53

#titleString

This is the title of the page.


# File 'app/models/simplec/page.rb', line 62

Class Method Details

.field(name, options = {}) ⇒ Object

Define a field on the page

There is as template for each type for customization located in:

app/views/shared/fields/_TYPE.html.erb

Defines a field on a subclass. This creates a getter and setter for the name passed in. The options are used when building the administration forms.

Regular dragonfly validations are available on :file and :image fields. markevans.github.io/dragonfly/models#validations

:string - yields a text input
:text - yields a textarea
:editor - yields a summernote editor
:file - yields a file field
:image - yields a file field with image preview

Options Hash (options):

  • :type (Symbol)

    one of :string (default), :text, :editor, :file, :image


102
103
104
105
106
107
108
109
110
111
# File 'app/models/simplec/page.rb', line 102

def self.field(name, options={})
  fields[name] = {name: name, type: :string}.merge(options)
  if FILE_FIELDS.member?(fields[name][:type])
    dragonfly_accessor name
    data_field :"#{name}_uid"
    data_field :"#{name}_name"
  else
    data_field(name)
  end
end

.field_names(type = nil) ⇒ Object

Return names of fields.

type: :file, is the only option


133
134
135
136
137
138
139
140
141
# File 'app/models/simplec/page.rb', line 133

def self.field_names(type=nil)
  _fields = case type
            when :file
              fields.select {|k, v| FILE_FIELDS.member?(v[:type])}
            else
              fields
            end
  _fields.keys
end

.fieldsHash


114
115
116
# File 'app/models/simplec/page.rb', line 114

def self.fields
  @fields ||= Hash.new
end

.type(type) ⇒ Class

Return a constantized type, whitelisted by known subclasses.

Raises:

  • (RuntimeError)

    if Page subclass isn't defined.


122
123
124
125
126
127
# File 'app/models/simplec/page.rb', line 122

def self.type(type)
  ::Page rescue raise '::Page not defined, define it in app/models'
  raise 'Unsupported Page Type; define in app/models/page/' unless ::Page.subclasses.map(&:name).
    member?(type)
  type.constantize
end

Instance Method Details

#build_pathString

Build the path of the page to be used in routing.

Used as a before validation hook.


168
169
170
171
# File 'app/models/simplec/page.rb', line 168

def build_path
  _pages = self.parents.reverse + [self]
  self.path = "/#{_pages.map(&:slug).reject(&:blank?).join('/')}"
end

#field_optionsObject

Return field options for building forms.


145
146
147
# File 'app/models/simplec/page.rb', line 145

def field_options
  self.class.fields.values
end

#find_embedded_imagesArray

Search all of the fields text and create an array of all found Simplec::EmbeddedImages.


190
191
192
193
194
195
196
# File 'app/models/simplec/page.rb', line 190

def find_embedded_images
  text = self.fields.values.join(' ')
  matches = text.scan(/ei=([^&]*)/)
  encoded_ids = matches.map(&:first)
  ids = encoded_ids.map { |eid| Base64.urlsafe_decode64(URI.unescape(eid)) }
  EmbeddedImage.includes(:embeddable).find(ids)
end

#layoutsArray

Get layout options.

See Simplec::Subdomain#layouts.


218
219
220
# File 'app/models/simplec/page.rb', line 218

def layouts
  @layouts ||= Subdomain.new.layouts
end

Set this instance as the #embeddable association on the

Simplec::EmbeddedImage

Used as an after_save hook.


204
205
206
207
208
209
210
211
# File 'app/models/simplec/page.rb', line 204

def link_embedded_images!
  images = self.find_embedded_images
  images.each do |image|
    raise AlreadyLinkedEmbeddedImage if image.embeddable &&
      image.embeddable != self
    image.update!(embeddable: self)
  end
end

#match_parent_subdomainSimplec::Subdomain

Sets the #subdomain t that of the parent.

All pages need to have a matching subdomain to parent page. Does nothing if there is no parent.

Used as a before validation hook.


181
182
183
184
# File 'app/models/simplec/page.rb', line 181

def match_parent_subdomain
  return unless self.parent
  self.subdomain = self.parent.subdomain
end

#parentsArray

List parents, closest to furthest.

This is a recursive, expensive call.


154
155
156
157
158
159
160
161
# File 'app/models/simplec/page.rb', line 154

def parents
  page, parents = self, Array.new
  while page.parent
    page = page.parent
    parents << page
  end
  parents
end