Class: Plum::Entry

Inherits:
ApplicationRecord show all
Includes:
SiteScoped, StaticCacheInvalidation
Defined in:
app/models/plum/entry.rb

Constant Summary collapse

HOMEPAGE_SLUG =

The page served at "/" — Plum resolves the homepage by this slug (convention over configuration). Its slug is locked and it can't be deleted while published, so a non-technical editor can't orphan the home page by renaming or removing it.

"home".freeze

Constants included from StaticCacheInvalidation

StaticCacheInvalidation::CACHE_IRRELEVANT_COLUMNS

Instance Method Summary collapse

Instance Method Details

#discard_draft!Object



91
92
93
# File 'app/models/plum/entry.rb', line 91

def discard_draft!
  update!(draft_data: nil)
end

#draft_field_value(handle) ⇒ Object



64
65
66
# File 'app/models/plum/entry.rb', line 64

def draft_field_value(handle)
  draft_data.to_h.dig("data", handle) || field_value(handle)
end

#draft_titleObject



60
61
62
# File 'app/models/plum/entry.rb', line 60

def draft_title
  draft_data.to_h["title"].presence || title
end

#field_value(handle) ⇒ Object



48
49
50
# File 'app/models/plum/entry.rb', line 48

def field_value(handle)
  data&.dig(handle)
end

#has_draft?Boolean

Working copy ("draft of a published entry"): pending edits stored in draft_data as { "title" => ..., "data" => ... }. The live title and data stay untouched until publish_draft!, so the public site never sees half-written content.

Returns:

  • (Boolean)


56
57
58
# File 'app/models/plum/entry.rb', line 56

def has_draft?
  draft_data.present?
end

#homepage?Boolean

Returns:

  • (Boolean)


95
96
97
# File 'app/models/plum/entry.rb', line 95

def homepage?
  slug == HOMEPAGE_SLUG
end

#publish_draft!(editor: nil) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'app/models/plum/entry.rb', line 77

def publish_draft!(editor: nil)
  return false unless has_draft?

  transaction do
    update!(
      title: draft_data["title"].presence || title,
      data: draft_data["data"] || data,
      draft_data: nil
    )
    record_revision!(editor: editor)
  end
  true
end

#record_revision!(editor: nil) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'app/models/plum/entry.rb', line 99

def record_revision!(editor: nil)
  identity = revision_editor_identity(editor)
  attributes = {
    site: site,
    editor_name: identity[:name],
    editor_email: identity[:email],
    editor_gid: identity[:gid],
    snapshot: {
      "title" => title,
      "slug" => slug,
      "status" => status,
      "published_at" => published_at&.iso8601,
      "data" => data.to_h.deep_dup,
      "term_ids" => term_ids
    }
  }
  attributes[:editor] = editor if editor.is_a?(Plum::User)

  # Autosave calls this on every save; identical content shouldn't pile
  # up as duplicate history entries.
  last = revisions.order(id: :desc).first
  return last if last && last.snapshot == attributes[:snapshot]

  revisions.create!(attributes)
end

#restore_revision!(revision, editor: nil) ⇒ Object

Raises:

  • (ArgumentError)


125
126
127
128
129
130
131
132
133
134
# File 'app/models/plum/entry.rb', line 125

def restore_revision!(revision, editor: nil)
  raise ArgumentError, "Revision does not belong to this entry" unless revision.entry_id == id && revision.site_id == site_id

  snapshot = revision.snapshot.to_h
  transaction do
    update!(snapshot.slice("title", "slug", "status", "published_at", "data"))
    self.term_ids = site.terms.where(id: Array(snapshot["term_ids"])).pluck(:id)
    record_revision!(editor: editor)
  end
end

#save_draft!(title: nil, data: {}) ⇒ Object



68
69
70
71
72
73
74
75
# File 'app/models/plum/entry.rb', line 68

def save_draft!(title: nil, data: {})
  base = draft_data.to_h
  merged = (base["data"] || self.data.to_h).merge(data.to_h)
  update!(draft_data: {
    "title" => title.presence || base["title"].presence || self.title,
    "data" => merged
  })
end

#translation_groupObject



136
137
138
139
# File 'app/models/plum/entry.rb', line 136

def translation_group
  source = origin || self
  [ source, *source.translations ].uniq.sort_by(&:locale)
end