Class: Discussion

Inherits:
ApplicationRecord show all
Includes:
Contextualization, WithDiscussionStatus, WithResponsibleModerator, WithScopedQueries
Defined in:
app/models/discussion.rb

Constant Summary

Constants included from WithScopedQueries

WithScopedQueries::SCOPING_METHODS

Constants included from WithResponsibleModerator

WithResponsibleModerator::MODERATOR_MAX_RESPONSIBLE_TIME

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Contextualization

#affable_expectation_results, #affable_test_results, #affable_tips, #expectation_results_visible?, #failed_expectation_results, #feedback_html, #first_test_result, #first_test_result_html, #humanized_expectation_results, #iconize, #queries_with_results, #result_html, #results_body_hidden?, #sanitized_affable_test_results, #single_visible_test_result?, #single_visual_result?, #single_visual_result_html, #test_result_html, #visible_expectation_results, #visible_status

Methods included from WithResponsibleModerator

#any_responsible?, #can_toggle_responsible?, #current_responsible_visible_for?, #no_current_responsible?, #responsible?, #toggle_responsible!

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

Class Method Details

.debatable_for(klazz, params) ⇒ Object



183
184
185
186
# File 'app/models/discussion.rb', line 183

def self.debatable_for(klazz, params)
  debatable_id = params[:"#{klazz.underscore}_id"]
  klazz.constantize.find(debatable_id)
end

Instance Method Details

#authorized?(user) ⇒ Boolean

Returns:

  • (Boolean)


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

def authorized?(user)
  initiator?(user) || user.try(:moderator_here?)
end

#commentable_by?(user) ⇒ Boolean

Returns:

  • (Boolean)


69
70
71
# File 'app/models/discussion.rb', line 69

def commentable_by?(user)
  user&.moderator_here? || (opened? && user.present?)
end

#extra_preview_htmlObject



168
169
170
171
172
# File 'app/models/discussion.rb', line 168

def extra_preview_html
  # FIXME this is buggy, because the extra
  # may have changed since the submission of this discussion
  exercise.assignment_for(initiator).extra_preview_html
end

#friendlyObject



89
90
91
# File 'app/models/discussion.rb', line 89

def friendly
  initiator.abbreviated_name
end

#has_messages?Boolean

Returns:

  • (Boolean)


140
141
142
# File 'app/models/discussion.rb', line 140

def has_messages?
  visible_messages.exists? || description.present?
end

#has_responses?Boolean

Returns:

  • (Boolean)


148
149
150
# File 'app/models/discussion.rb', line 148

def has_responses?
  responses_count > 0
end

#has_submission?Boolean

Returns:

  • (Boolean)


77
78
79
# File 'app/models/discussion.rb', line 77

def has_submission?
  submission.solution.present?
end

#has_validated_responses?Boolean

Returns:

  • (Boolean)


152
153
154
# File 'app/models/discussion.rb', line 152

def has_validated_responses?
  validated_messages_count > 0
end

#initiator?(user) ⇒ Boolean

Returns:

  • (Boolean)


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

def initiator?(user)
  user.try(:uid) == initiator.uid
end

#last_message_dateObject



85
86
87
# File 'app/models/discussion.rb', line 85

def last_message_date
  visible_messages.last&.created_at || created_at
end

#mark_subscriptions_as_unread!(user) ⇒ Object



101
102
103
# File 'app/models/discussion.rb', line 101

def mark_subscriptions_as_unread!(user)
  subscriptions.where.not(user: user).each(&:unread!)
end


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

def navigable_content_in(_)
  nil
end

#reachable_status_for?(user, status) ⇒ Boolean

Returns:

  • (Boolean)


126
127
128
# File 'app/models/discussion.rb', line 126

def reachable_status_for?(user, status)
  reachable_statuses_for(user).include? status
end

#reachable_statuses_for(user) ⇒ Object



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

def reachable_statuses_for(user)
  return [] unless authorized?(user)
  status.reachable_statuses_for(user, self)
end

#read_by?(user) ⇒ Boolean

Returns:

  • (Boolean)


81
82
83
# File 'app/models/discussion.rb', line 81

def read_by?(user)
  subscription_for(user).read
end

#requires_attention?Boolean

Returns:

  • (Boolean)


160
161
162
# File 'app/models/discussion.rb', line 160

def requires_attention?
  no_current_responsible? && status.requires_attention_for?(self)
end

#requires_attention_for?(user) ⇒ Boolean

Returns:

  • (Boolean)


156
157
158
# File 'app/models/discussion.rb', line 156

def requires_attention_for?(user)
  user&.moderator_here? && requires_attention?
end

#responses_countObject



144
145
146
# File 'app/models/discussion.rb', line 144

def responses_count
  visible_messages.where.not(sender: initiator).count
end

#subjectObject

TODO remove this once discussions generate notifications



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

def subject
  'discussion'
end

#submit_message!(message, user) ⇒ Object



105
106
107
108
109
110
111
# File 'app/models/discussion.rb', line 105

def submit_message!(message, user)
  message.merge!(sender: user)
  messages.create(message)
  user.subscribe_to! self
  mark_subscriptions_as_unread!(user)
  no_responsible! if responsible?(user)
end

#subscribable?Boolean

Returns:

  • (Boolean)


73
74
75
# File 'app/models/discussion.rb', line 73

def subscribable?
  opened? || solved?
end

#subscribe_initiator!Object



164
165
166
# File 'app/models/discussion.rb', line 164

def subscribe_initiator!
  initiator.subscribe_to! self
end

#subscription_for(user) ⇒ Object



93
94
95
# File 'app/models/discussion.rb', line 93

def subscription_for(user)
  subscriptions.find_by(user: user)
end

#targetObject



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

def target
  self
end

#try_solve!Object



51
52
53
54
55
# File 'app/models/discussion.rb', line 51

def try_solve!
  if opened?
    update! status: reachable_statuses_for(initiator).first
  end
end

#update_counters!Object



174
175
176
177
178
179
180
181
# File 'app/models/discussion.rb', line 174

def update_counters!
  messages_query = messages_by_updated_at
  validated_messages = messages_query.select &:validated?
  has_moderator_response = messages_query.find { |it| it.validated? || it.question? }&.validated?
  update! messages_count: messages_query.count,
          validated_messages_count: validated_messages.count,
          requires_moderator_response: !has_moderator_response
end

#update_status!(status, user) ⇒ Object



130
131
132
133
134
135
136
137
138
# File 'app/models/discussion.rb', line 130

def update_status!(status, user)
  if reachable_status_for?(user, status)
    update! status: status,
            status_updated_by: user,
            status_updated_at: Time.current

    no_responsible! if responsible?(user)
  end
end

#upvote_for(user) ⇒ Object



97
98
99
# File 'app/models/discussion.rb', line 97

def upvote_for(user)
  upvotes.find_by(user: user)
end

#used_in?(organization) ⇒ Boolean

Returns:

  • (Boolean)


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

def used_in?(organization)
  organization == self.organization
end

#visible_messagesObject



47
48
49
# File 'app/models/discussion.rb', line 47

def visible_messages
  messages.visible
end