Class: Guide

Inherits:
Content show all
Includes:
WithAssignmentsBatch, WithExpectations, WithLanguage, WithStats
Defined in:
app/models/guide.rb

Constant Summary collapse

BASIC_RESOURCE_FIELDS =
%i(
authors beta collaborators corollary
custom_expectations expectations extra id_format
learn_more private settings sources teacher_info type)

Instance Method Summary collapse

Methods included from WithStats

#started?, #stats_for

Methods included from WithExpectations

#ensure_expectations_format, #expectations=, #expectations_yaml, #expectations_yaml=, #raw_expectations

Methods included from WithAssignmentsBatch

#assignments_for, #find_assignments_for, #statuses_for

Methods inherited from Content

#fork_to!, #public?, #to_resource_h

Methods included from WithUsages

#content_used_in?, #navigable_content_in, #usage_in_organization, #usage_in_organization_of_type, #used_in?

Methods included from WithSlug

#normalize_slug!, #rebase!, #rebased_dup, #transparent_id, #transparent_params

Methods included from WithProgress

#completed_for?, #completion_percentage_for, #dirty_progress_if_structural_children_changed!, #dirty_progresses!, #has_progress_for?, #once_completed_for?, #progress_for

Methods included from Mumuki::Domain::Syncable

#platform_class_name, #sync_key

Methods inherited from ApplicationRecord

active_between, aggregate_of, all_except, defaults, #delete, #destroy!, enum_prefixed_translations_for, numbered, organic_on, resource_fields, #save, #save_and_notify!, #save_and_notify_changes!, serialize_symbolized_hash_array, teaser_on, #update_and_notify!, update_or_create!, whitelist_attributes, with_pg_retry, with_temporary_token

Methods included from WithPgLock

#with_pg_lock

Instance Method Details

#as_complement_of(book) ⇒ Object

FIXME duplication



117
118
119
# File 'app/models/guide.rb', line 117

def as_complement_of(book) #FIXME duplication
  book.complements.find_by(guide_id: id) || Complement.new(guide: self, book: book)
end

#as_lesson_of(topic) ⇒ Object



113
114
115
# File 'app/models/guide.rb', line 113

def as_lesson_of(topic)
  topic.lessons.find_by(guide_id: id) || Lesson.new(guide: self, topic: topic)
end

#chapterObject



37
38
39
# File 'app/models/guide.rb', line 37

def chapter
  lesson.try(:chapter) #FIXME temporary
end

#clear_progress!(user, organization = Organization.current) ⇒ Object



25
26
27
28
29
30
31
# File 'app/models/guide.rb', line 25

def clear_progress!(user, organization=Organization.current)
  transaction do
    exercises.each do |exercise|
      exercise.find_assignment_for(user, organization)&.destroy!
    end
  end
end

#done_for?(user) ⇒ Boolean

Returns:

  • (Boolean)


65
66
67
# File 'app/models/guide.rb', line 65

def done_for?(user)
  stats_for(user).done?
end

#exercises_countObject



41
42
43
# File 'app/models/guide.rb', line 41

def exercises_count
  exercises.count
end

#first_exerciseObject



57
58
59
# File 'app/models/guide.rb', line 57

def first_exercise
  exercises.first
end

#fork_children_into!(dup, _organization, _syncer) ⇒ Object

Forking



127
128
129
# File 'app/models/guide.rb', line 127

def fork_children_into!(dup, _organization, _syncer)
  dup.exercises = exercises.map(&:dup)
end

#import_from_resource_h!(resource_h) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'app/models/guide.rb', line 74

def import_from_resource_h!(resource_h)
  dirty_progress_if_structural_children_changed! do
    self.assign_attributes whitelist_attributes(resource_h)
    self.language = Language.for_name(resource_h.dig(:language, :name))
    self.save!

    resource_h[:exercises]&.each_with_index do |e, i|
      exercise = Exercise.find_by(guide_id: self.id, bibliotheca_id: e[:id])
      exercise_type = e[:type] || 'problem'

      exercise = exercise ?
          exercise.ensure_type!(exercise_type.as_module_name) :
          exercise_type.as_module.new(guide_id: self.id, bibliotheca_id: e[:id])

      exercise.import_from_resource_h! (i+1), e
    end

    new_ids = resource_h[:exercises].map { |it| it[:id] }
    self.exercises.where.not(bibliotheca_id: new_ids).destroy_all

    reload
  end
end

#lessonObject



33
34
35
# File 'app/models/guide.rb', line 33

def lesson
  usage_in_organization_of_type Lesson
end

#locate_exercise!(bibliotheca_id) ⇒ Object

Finds an exercise by bibliotheca_id within this guide



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

def locate_exercise!(bibliotheca_id)
  exercises.find_by!(bibliotheca_id: bibliotheca_id)
end

#next_exercise(user) ⇒ Object



45
46
47
48
49
50
51
# File 'app/models/guide.rb', line 45

def next_exercise(user)
  if user.present?
    user.next_exercise_at(self)
  else
    first_exercise
  end
end

#pending_exercises(user) ⇒ Object



53
54
55
# File 'app/models/guide.rb', line 53

def pending_exercises(user)
  Exercise.with_pending_assignments_for(user, exercises)
end

#resettable?Boolean

Returns:

  • (Boolean)


121
122
123
# File 'app/models/guide.rb', line 121

def resettable?
  usage_in_organization.resettable?
end

#search_tagsObject



61
62
63
# File 'app/models/guide.rb', line 61

def search_tags
  exercises.flat_map(&:search_tags).uniq
end

#to_expanded_resource_h(options = {}) ⇒ Object

Keep this list up to date with Mumuki::Domain::Store::Github::GuideSchema



100
101
102
103
104
105
106
107
# File 'app/models/guide.rb', line 100

def to_expanded_resource_h(options={})
  as_json(only: BASIC_RESOURCE_FIELDS)
    .symbolize_keys
    .merge(super)
    .merge(exercises: exercises.map { |it| it.to_resource_h(options) })
    .merge(language: language.to_embedded_resource_h)
    .tap { |it| it.markdownified!(:corollary, :description, :teacher_info) if options[:markdownified] }
end

#to_markdownified_resource_hObject



109
110
111
# File 'app/models/guide.rb', line 109

def to_markdownified_resource_h
  to_resource_h(markdownified: true)
end