Class: Artefact

Inherits:
Object
  • Object
show all
Includes:
Mongoid::Document, Mongoid::Timestamps, Taggable
Defined in:
app/models/artefact.rb

Constant Summary collapse

GOVSPEAK_FIELDS =
[]
8
FORMATS_BY_DEFAULT_OWNING_APP =
{
  "publisher"               => ["answer",
                                "business_support",
                                "campaign",
                                "completed_transaction",
                                "guide",
                                "help_page",
                                "licence",
                                "local_transaction",
                                "place",
                                "programme",
                                "simple_smart_answer",
                                "transaction",
                                "video"],
  "smartanswers"            => ["smart-answer"],
  "custom-application"      => ["custom-application"], # In this case the owning_app is overriden. eg calendars, licencefinder
  "travel-advice-publisher" => ["travel-advice"],
  "specialist-publisher"    => ["aaib_report",
                                "cma_case",
                                "drug_safety_update",
                                "international_development_fund",
                                "maib_report",
                                "manual",
                                "manual-change-history",
                                "manual-section",
                                "medical_safety_alert",
                                "raib_report"],
  "finder-api"              => ["finder",
                                "finder_email_signup"],
  "whitehall"               => ["announcement",
                                "authored_article",
                                "case_study",
                                "consultation",
                                "corporate_information_page",
                                "corporate_report",
                                "correspondence",
                                "decision",
                                "detailed_guide",
                                "document_collection",
                                "draft_text",
                                "fatality_notice",
                                "foi_release",
                                "form",
                                "government_response",
                                "guidance",
                                "impact_assessment",
                                "independent_report",
                                "international_treaty",
                                "map",
                                "national_statistics",
                                "news_story",
                                "notice",
                                "oral_statement",
                                "policy",
                                "policy_paper",
                                "press_release",
                                "promotional",
                                "publication",
                                "regulation",
                                "research",
                                "speaking_notes",
                                "statistical_data_set",
                                "statistics",
                                "statutory_guidance",
                                "supporting_page",
                                "transcript",
                                "transparency",
                                "world_location_news_article",
                                "worldwide_priority",
                                "written_statement"],
  "panopticon"              => ["specialist_sector"],
}.freeze
FORMATS =
FORMATS_BY_DEFAULT_OWNING_APP.values.flatten
KIND_TRANSLATIONS =
{
  "standard transaction link"        => "transaction",
  "local authority transaction link" => "local_transaction",
  "completed/done transaction" => "completed_transaction",
  "benefit / scheme"                 => "programme",
  "find my nearest"                  => "place",
}.tap { |h| h.default_proc = -> _, k { k } }.freeze

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Taggable

included, #set_primary_tag_of_type, #set_tags_of_type, #tags, #tags=, #tags_of_type

Class Method Details

.default_app_for_format(format) ⇒ Object



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

def self.default_app_for_format(format)
  FORMATS_BY_DEFAULT_OWNING_APP.detect { |app, formats| formats.include?(format) }.first
end

.find_by_slug(s) ⇒ Object



189
190
191
# File 'app/models/artefact.rb', line 189

def self.find_by_slug(s)
  where(slug: s).first
end

.from_param(slug_or_id) ⇒ Object



312
313
314
315
316
# File 'app/models/artefact.rb', line 312

def self.from_param(slug_or_id)
  find_by_slug(slug_or_id) || find(slug_or_id)
rescue BSON::InvalidObjectId
  raise Mongoid::Errors::DocumentNotFound.new(self, slug_or_id)
end

.in_alphabetical_orderObject



185
186
187
# File 'app/models/artefact.rb', line 185

def self.in_alphabetical_order
  order_by([[:name, :asc]])
end

Instance Method Details

#admin_url(options = {}) ⇒ Object



213
214
215
216
217
# File 'app/models/artefact.rb', line 213

def admin_url(options = {})
  [ "#{Plek.current.find(owning_app)}/admin/publications/#{id}",
    options.to_query
  ].reject(&:blank?).join("?")
end

#any_editions_ever_published?Boolean

Returns:

  • (Boolean)


286
287
288
289
# File 'app/models/artefact.rb', line 286

def any_editions_ever_published?
  Edition.where(panopticon_id: self.id,
                :state.in => ['published', 'archived']).any?
end

#any_editions_published?Boolean

Returns:

  • (Boolean)


282
283
284
# File 'app/models/artefact.rb', line 282

def any_editions_published?
  Edition.where(panopticon_id: self.id, state: 'published').any?
end

#archive_editionsObject



303
304
305
306
307
308
309
310
# File 'app/models/artefact.rb', line 303

def archive_editions
  if state == 'archived'
    Edition.where(panopticon_id: self.id, :state.nin => ["archived"]).each do |edition|
      edition.new_action(self, "note", comment: "Artefact has been archived. Archiving this edition.")
      edition.archive!
    end
  end
end

#archived?Boolean

Returns:

  • (Boolean)


356
357
358
# File 'app/models/artefact.rb', line 356

def archived?
  self.state == "archived"
end

#as_json(options = {}) ⇒ Object

TODO: Replace this nonsense with a proper API layer.



220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'app/models/artefact.rb', line 220

def as_json(options={})
  super.tap { |hash|
    if hash["tag_ids"]
      hash["tags"] = Tag.by_tag_ids(hash["tag_ids"]).map(&:as_json)
    else
      hash["tag_ids"] = []
      hash["tags"] = []
    end

    if self.primary_section
      hash['primary_section'] = self.primary_section.tag_id
    end

    unless options[:ignore_related_artefacts]
      hash["related_items"] = published_related_artefacts.map do |a|
        {"artefact" => a.as_json(ignore_related_artefacts: true)}
      end
    end
    hash.delete("related_artefacts")
    hash.delete("related_artefact_ids")
    hash["id"] = hash.delete("_id")

    # Add a section identifier if needed
    hash["section"] ||= section
  }
end

#languageObject

Fallback to english if no language is present



204
205
206
# File 'app/models/artefact.rb', line 204

def language
  attributes['language'] || "en"
end

#live?Boolean

Returns:

  • (Boolean)


360
361
362
# File 'app/models/artefact.rb', line 360

def live?
  self.state == "live"
end

#need_id=(new_need_id) ⇒ Object



368
369
370
371
372
373
# File 'app/models/artefact.rb', line 368

def need_id=(new_need_id)
  super

  need_ids << new_need_id if new_need_id.present? && ! need_ids.include?(new_need_id)
  new_need_id
end

#normaliseObject



208
209
210
211
# File 'app/models/artefact.rb', line 208

def normalise
  return unless kind.present?
  self.kind = KIND_TRANSLATIONS[kind.to_s.downcase.strip]
end

Pass in the desired scope, eg self.related_artefacts.live, get back the items in the order they were set in, rather than natural order



259
260
261
# File 'app/models/artefact.rb', line 259

def ordered_related_artefacts(scope_or_array = self.related_artefacts)
  scope_or_array.sort_by { |artefact| related_artefact_ids.index(artefact.id) }
end


247
248
249
250
251
252
253
254
255
# File 'app/models/artefact.rb', line 247

def published_related_artefacts
  related_artefacts.select do |related_artefact|
    if related_artefact.owning_app == "publisher"
      related_artefact.any_editions_published?
    else
      true
    end
  end
end

#record_action(action_type, options = {}) ⇒ Object



338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
# File 'app/models/artefact.rb', line 338

def record_action(action_type, options={})
  user = options[:user]
  current_snapshot = snapshot
  last_snapshot = actions.last ? actions.last.snapshot : nil
  unless current_snapshot == last_snapshot
    new_action = actions.build(
      user: user,
      action_type: action_type,
      snapshot: current_snapshot
    )
    # Mongoid will not fire creation callbacks on embedded documents, so we
    # need to trigger this manually. There is a `cascade_callbacks` option on
    # `embeds_many`, but it doesn't appear to trigger creation events on
    # children when an update event fires on the parent
    new_action.set_created_at
  end
end

#record_create_actionObject



330
331
332
# File 'app/models/artefact.rb', line 330

def record_create_action
  record_action "create"
end

#record_update_actionObject



334
335
336
# File 'app/models/artefact.rb', line 334

def record_update_action
  record_action "update"
end


263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# File 'app/models/artefact.rb', line 263

def related_artefacts_grouped_by_distance(scope_or_array = self.related_artefacts)
  groups = { "subsection" => [], "section" => [], "other" => [] }
  scoped_artefacts = ordered_related_artefacts(scope_or_array)

  if primary_tag = self.primary_section
    groups['subsection'] = scoped_artefacts.select {|a| a.tag_ids.include?(primary_tag.tag_id) }

    if primary_tag.parent_id.present?
      pattern = Regexp.new "^#{Regexp.quote(primary_tag.parent_id)}\/.+"
      groups['section'] = scoped_artefacts.reject {|a| groups['subsection'].include?(a) }.select {|a|
        a.tag_ids.grep(pattern).count > 0
      }
    end
  end
  groups['other'] = scoped_artefacts.reject {|a| (groups['subsection'] + groups['section']).include?(a) }

  groups
end

#save_as(user, options = {}) ⇒ Object



323
324
325
326
327
328
# File 'app/models/artefact.rb', line 323

def save_as(user, options={})
  default_action = new_record? ? "create" : "update"
  action_type = options.delete(:action_type) || default_action
  record_action action_type, user: user
  save(options)
end

#sectionObject

The old-style section string identifier, of the form ‘Crime:Prisons’



194
195
196
197
198
199
200
201
# File 'app/models/artefact.rb', line 194

def section
  return '' unless self.primary_section
  if primary_section.parent
    [primary_section.parent.title, primary_section.title].join ':'
  else
    primary_section.title
  end
end

#snapshotObject



364
365
366
# File 'app/models/artefact.rb', line 364

def snapshot
  attributes.except "_id", "created_at", "updated_at", "actions"
end

#update_attributes_as(user, *args) ⇒ Object



318
319
320
321
# File 'app/models/artefact.rb', line 318

def update_attributes_as(user, *args)
  assign_attributes(*args)
  save_as user
end

#update_editionsObject



291
292
293
294
295
296
297
298
299
300
301
# File 'app/models/artefact.rb', line 291

def update_editions
  case state
  when 'draft'
    Edition.where(:state.nin => ["archived"],
                  panopticon_id: self.id).each do |edition|
      edition.update_slug_from_artefact(self)
    end
  when 'archived'
    archive_editions
  end
end