Class: Edition

Inherits:
Object
  • Object
show all
Includes:
Mongoid::Document, Mongoid::Timestamps, RecordableActions, Workflow
Defined in:
app/models/edition.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Workflow

#can_destroy?, #check_can_delete_and_notify, #denormalise_users!, #error_description, #fact_checked?, #important_note, #in_progress?, #locked_for_edits?, #mark_as_rejected, #notify_siblings_of_new_edition, #perform_event_without_validations, #previous_edition, #status_text

Class Method Details

.find_and_identify(slug, edition) ⇒ Object



244
245
246
247
248
249
250
251
252
253
254
# File 'app/models/edition.rb', line 244

def self.find_and_identify(slug, edition)
  scope = where(slug: slug)

  if edition.present? and edition == "latest"
    scope.order_by(version_number: :asc).last
  elsif edition.present?
    scope.where(version_number: edition).first
  else
    scope.where(state: "published").order(version_number: :desc).first
  end
end

.find_or_create_from_panopticon_data(panopticon_id, importing_user) ⇒ Object



231
232
233
234
235
236
237
238
239
240
241
242
# File 'app/models/edition.rb', line 231

def self.find_or_create_from_panopticon_data(panopticon_id, importing_user)
  existing_publication = Edition.where(panopticon_id: panopticon_id)
    .order_by(version_number: :desc).first
  return existing_publication if existing_publication

  raise "Artefact not found" unless  = Artefact.find(panopticon_id)

  importing_user.create_edition(.kind.to_sym,
    panopticon_id: .id,
    slug: .slug,
    title: .name)
end

Instance Method Details

#artefactObject



307
308
309
# File 'app/models/edition.rb', line 307

def artefact
  Artefact.find(panopticon_id)
end

#broadcast_action(callback_action) ⇒ Object

Stop broadcasting a delete message unless there are no siblings.



277
278
279
280
281
# File 'app/models/edition.rb', line 277

def broadcast_action(callback_action)
  unless callback_action == "destroyed" and self.siblings.any?
    super(callback_action)
  end
end

#build_clone(target_class = nil) ⇒ Object



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'app/models/edition.rb', line 181

def build_clone(target_class=nil)
  unless state == "published"
    raise "Cloning of non published edition not allowed"
  end
  unless can_create_new_edition?
    raise "Cloning of a published edition when an in-progress edition exists
           is not allowed"
  end

  target_class = self.class unless target_class
  new_edition = target_class.new(version_number: get_next_version_number)

  fields_to_copy(target_class).each do |attr|
    new_edition[attr] = read_attribute(attr)
  end

  # If the type is changing, then take the combined body (whole_body) from
  # the old and decide where to put it in the new.
  #
  # Where the type is not changing, the body will already have been copied
  # above.
  #
  # We don't need to copy parts between Parted types here, because the
  # Parted module does that.
  if target_class != self.class && !cloning_between_parted_types?(new_edition)
    new_edition.clone_whole_body_from(self)
  end

  new_edition
end

#can_create_new_edition?Boolean

Returns:

  • (Boolean)


102
103
104
105
# File 'app/models/edition.rb', line 102

def can_create_new_edition?
  return false if retired_format?
  !scheduled_for_publishing? && subsequent_siblings.in_progress.empty?
end

#check_for_archived_artefactObject



293
294
295
296
297
298
299
300
301
302
303
304
305
# File 'app/models/edition.rb', line 293

def check_for_archived_artefact
  if panopticon_id
    a = Artefact.find(panopticon_id)
    if a.state == "archived" and changes.any?
      # If we're only changing the state to archived, that's ok
      # Any other changes are not allowed
      allowed_keys = ["state", "updated_at"]
      unless ((changes.keys - allowed_keys).empty?) and state == "archived"
        raise "Editing of an edition with an Archived artefact is not allowed"
      end
    end
  end
end

#clone_whole_body_from(origin_edition) ⇒ Object



212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'app/models/edition.rb', line 212

def clone_whole_body_from(origin_edition)
  if self.respond_to?(:parts)
    self.setup_default_parts if self.respond_to?(:setup_default_parts)
    self.parts.build(title: "Part One", body: origin_edition.whole_body, slug: "part-one")
  elsif self.respond_to?(:more_information=)
    self.more_information = origin_edition.whole_body
  elsif self.respond_to?(:body=)
    self.body = origin_edition.whole_body
  elsif self.respond_to?(:licence_overview=)
    self.licence_overview = origin_edition.whole_body
  else
    raise "Nowhere to copy whole_body content for conversion from: #{origin_edition.class} to: #{self.class}"
  end
end

#cloning_between_parted_types?(new_edition) ⇒ Boolean

Returns:

  • (Boolean)


227
228
229
# File 'app/models/edition.rb', line 227

def cloning_between_parted_types?(new_edition)
  self.respond_to?(:parts) && new_edition.respond_to?(:parts)
end

#destroy_artefactObject

When we delete an edition is the only one in its series we delete the associated artefact to remove all trace of the item from the system.

We don’t do this by notifying panopticon as this will only ever happen for artefacts representing editions that haven’t been published (and therefore aren’t registered in the rest of the) system.



319
320
321
322
323
# File 'app/models/edition.rb', line 319

def destroy_artefact
  if can_destroy? && siblings.empty?
    Artefact.find(self.panopticon_id).destroy
  end
end

#fields_to_copy(target_class) ⇒ Object

If the new clone is of the same type, we can copy all its fields over; if we are changing the type of the edition, any fields other than the base fields will likely be meaningless.



173
174
175
176
177
178
179
# File 'app/models/edition.rb', line 173

def fields_to_copy(target_class)
  if target_class == self.class
    base_field_keys + type_specific_field_keys
  else
    base_field_keys + common_type_specific_field_keys(target_class)
  end
end

#first_edition_of_publishedObject



137
138
139
# File 'app/models/edition.rb', line 137

def first_edition_of_published
  series.archived_or_published.order(version_number: "asc").first
end

#formatObject



256
257
258
# File 'app/models/edition.rb', line 256

def format
  self.class.to_s.gsub("Edition", "")
end

#format_nameObject



260
261
262
# File 'app/models/edition.rb', line 260

def format_name
  format
end

#get_next_version_numberObject



145
146
147
148
# File 'app/models/edition.rb', line 145

def get_next_version_number
  latest_version = series.order(version_number: "desc").first.version_number
  latest_version + 1
end

#has_ever_been_published?Boolean

Returns:

  • (Boolean)


133
134
135
# File 'app/models/edition.rb', line 133

def has_ever_been_published?
  series.map(&:state).include?('published')
end

#has_sibling_in_progress?Boolean

Returns:

  • (Boolean)


272
273
274
# File 'app/models/edition.rb', line 272

def has_sibling_in_progress?
  ! sibling_in_progress.nil?
end

#has_video?Boolean

Returns:

  • (Boolean)


264
265
266
# File 'app/models/edition.rb', line 264

def has_video?
  false
end

#historyObject



70
71
72
# File 'app/models/edition.rb', line 70

def history
  series.order([:version_number, :desc])
end

#in_progress_siblingObject



98
99
100
# File 'app/models/edition.rb', line 98

def in_progress_sibling
  subsequent_siblings.in_progress.order(version_number: "desc").first
end

#indexable_contentObject



150
151
152
# File 'app/models/edition.rb', line 150

def indexable_content
  respond_to?(:parts) ? indexable_content_with_parts : indexable_content_without_parts
end

#indexable_content_with_partsObject



162
163
164
165
166
167
168
# File 'app/models/edition.rb', line 162

def indexable_content_with_parts
  content = indexable_content_without_parts
  return content unless published_edition
  parts.inject([content]) { |acc, part|
    acc.concat([part.title, Govspeak::Document.new(part.body).to_text])
  }.compact.join(" ").strip
end

#indexable_content_without_partsObject



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

def indexable_content_without_parts
  if respond_to?(:body)
    "#{Govspeak::Document.new(body).to_text}".strip
  else
    ""
  end
end

#latest_change_noteObject



119
120
121
122
123
# File 'app/models/edition.rb', line 119

def latest_change_note
  if latest_major_update.present?
    latest_major_update.change_note
  end
end

#latest_edition?Boolean

Returns:

  • (Boolean)


86
87
88
# File 'app/models/edition.rb', line 86

def latest_edition?
  subsequent_siblings.empty?
end

#latest_major_updateObject



115
116
117
# File 'app/models/edition.rb', line 115

def latest_major_update
  major_updates_in_series.first
end

#major_updates_in_seriesObject



111
112
113
# File 'app/models/edition.rb', line 111

def major_updates_in_series
  history.published.major_updates
end

#meta_dataObject



141
142
143
# File 'app/models/edition.rb', line 141

def 
  PublicationMetadata.new self
end

#previous_published_editionObject



94
95
96
# File 'app/models/edition.rb', line 94

def previous_published_edition
  series.where(state: "published").order(version_number: "desc").second
end

#previous_siblingsObject



78
79
80
# File 'app/models/edition.rb', line 78

def previous_siblings
  siblings.where(:version_number.lt => version_number).order(version_number: "asc")
end

#public_updated_atObject



125
126
127
128
129
130
131
# File 'app/models/edition.rb', line 125

def public_updated_at
  if latest_major_update.present?
    latest_major_update.updated_at
  elsif has_ever_been_published?
    first_edition_of_published.updated_at
  end
end

#published_editionObject



90
91
92
# File 'app/models/edition.rb', line 90

def published_edition
  series.where(state: "published").order(version_number: "desc").first
end

#retired_format?Boolean

Returns:

  • (Boolean)


107
108
109
# File 'app/models/edition.rb', line 107

def retired_format?
  Artefact::RETIRED_FORMATS.include? format.underscore
end

#safe_to_preview?Boolean

Returns:

  • (Boolean)


268
269
270
# File 'app/models/edition.rb', line 268

def safe_to_preview?
  !archived?
end

#seriesObject



66
67
68
# File 'app/models/edition.rb', line 66

def series
  Edition.where(panopticon_id: panopticon_id)
end

#siblingsObject



74
75
76
# File 'app/models/edition.rb', line 74

def siblings
  series.excludes(id: id)
end

#subsequent_siblingsObject



82
83
84
# File 'app/models/edition.rb', line 82

def subsequent_siblings
  siblings.where(:version_number.gt => version_number).order(version_number: "asc")
end

#update_slug_from_artefact(artefact) ⇒ Object



288
289
290
291
# File 'app/models/edition.rb', line 288

def update_slug_from_artefact(artefact)
  self.slug = artefact.slug
  self.save!
end

#was_publishedObject



283
284
285
286
# File 'app/models/edition.rb', line 283

def was_published
  previous_siblings.each { |s| s.perform_event_without_validations(:archive) }
  notify_siblings_of_published_edition
end