Class: Topic

Inherits:
ApplicationRecord show all
Includes:
BaseModel, Likeable, MarkdownBody, Mentionable, Redis::Objects, Searchable, SoftDelete
Defined in:
app/models/topic.rb

Constant Summary

Constants included from ApplicationHelper

ApplicationHelper::ALLOW_ATTRIBUTES, ApplicationHelper::ALLOW_TAGS, ApplicationHelper::EMPTY_STRING, ApplicationHelper::LANGUAGES_LISTS, ApplicationHelper::MOBILE_USER_AGENTS

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Mentionable

#delete_notifiaction_mentions, #extract_mentioned_users, #mentioned_user_logins, #mentioned_users, #no_mention_users, #send_mention_notification

Methods included from SoftDelete

#deleted?

Methods included from ApplicationHelper

#admin?, #birthday_tag, #cache, #cached_asset_path, #controller_javascript_include_tag, #controller_stylesheet_link_tag, #highlight, #icon_tag, #insert_code_menu_items_tag, #javascript_include_tag_with_cached, #memory_cache, #mobile?, #notice_message, #owner?, #random_tips, #render_list, #render_page_title, #sanitize_markdown, #spaceless, #stylesheet_link_tag_with_cached, #timeago, #wiki_editor?

Methods included from Likeable

#liked_by_user?

Methods included from BaseModel

#pull, #push

Instance Attribute Details

#admin_editingObject

临时存储检测用户是否读过的结果


20
21
22
# File 'app/models/topic.rb', line 20

def admin_editing
  @admin_editing
end

#read_stateObject

临时存储检测用户是否读过的结果


20
21
22
# File 'app/models/topic.rb', line 20

def read_state
  @read_state
end

Class Method Details

.fields_for_listObject


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

def self.fields_for_list
  columns = %w(body body_html who_deleted follower_ids)
  select(column_names - columns.map(&:to_s))
end

.notify_topic_created(topic_id) ⇒ Object


191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'app/models/topic.rb', line 191

def self.notify_topic_created(topic_id)
  topic = Topic.find_by_id(topic_id)
  return if topic.blank?

  notified_user_ids = topic.mentioned_user_ids

  follower_ids = (topic.user.try(:follower_ids) || [])
  follower_ids.uniq!

  # 给关注者发通知
  default_note = { notify_type: 'topic', target_type: "Topic", target_id: topic.id, actor_id: topic.user_id }
  Notification.bulk_insert(set_size: 100) do |worker|
    follower_ids.each do |uid|
      # 排除同一个回复过程中已经提醒过的人
      next if notified_user_ids.include?(uid)
      # 排除回帖人
      next if uid == topic.user_id
      note = default_note.merge(user_id: uid)
      worker.add(note)
    end
  end

  true
end

.notify_topic_node_changed(topic_id, node_id) ⇒ Object


216
217
218
219
220
221
222
223
224
225
226
227
# File 'app/models/topic.rb', line 216

def self.notify_topic_node_changed(topic_id, node_id)
  topic = Topic.find_by_id(topic_id)
  return if topic.blank?
  node = Node.find_by_id(node_id)
  return if node.blank?

  Notification.create notify_type: 'node_changed',
                      user_id: topic.user_id,
                      target: topic,
                      second_target: node
  true
end

.topic_index_hide_node_idsObject


87
88
89
# File 'app/models/topic.rb', line 87

def self.topic_index_hide_node_ids
  Setting.node_ids_hide_in_topics_index.to_s.split(',').collect(&:to_i)
end

Instance Method Details

#as_indexed_json(options = {}) ⇒ Object


70
71
72
73
74
75
76
# File 'app/models/topic.rb', line 70

def as_indexed_json(options={})
  {
    title: self.title,
    body: self.full_body,
    node_name: self.node_name
  }
end

#async_create_reply_notifyObject


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

def async_create_reply_notify
  NotifyTopicJob.perform_later(id)
end

#auto_correct_titleObject


97
98
99
100
101
102
# File 'app/models/topic.rb', line 97

def auto_correct_title
  CORRECT_CHARS.each do |chars|
    title.gsub!(chars[0], chars[1])
  end
  title.auto_space!
end

#ban!Object


182
183
184
# File 'app/models/topic.rb', line 182

def ban!
  update_attributes(lock_node: true, node_id: Node.no_point_id, admin_editing: true)
end

#destroyObject


166
167
168
169
# File 'app/models/topic.rb', line 166

def destroy
  super
  delete_notifiaction_mentions
end

#destroy_by(user) ⇒ Object

删除并记录删除人


160
161
162
163
164
# File 'app/models/topic.rb', line 160

def destroy_by(user)
  return false if user.blank?
  update_attribute(:who_deleted, user.)
  destroy
end

#excellent?Boolean

Returns:

  • (Boolean)

178
179
180
# File 'app/models/topic.rb', line 178

def excellent?
  excellent >= 1
end

#floor_of_reply(reply) ⇒ Object


186
187
188
189
# File 'app/models/topic.rb', line 186

def floor_of_reply(reply)
  reply_index = reply_ids.index(reply.id)
  reply_index + 1
end

#followed?(uid) ⇒ Boolean

Returns:

  • (Boolean)

119
120
121
# File 'app/models/topic.rb', line 119

def followed?(uid)
  follower_ids.include?(uid)
end

#full_bodyObject


83
84
85
# File 'app/models/topic.rb', line 83

def full_body
  ([self.body] + self.replies.pluck(:body)).join('\n\n')
end

#init_last_active_mark_on_createObject


110
111
112
# File 'app/models/topic.rb', line 110

def init_last_active_mark_on_create
  self.last_active_mark = Time.now.to_i
end

#pull_follower(uid) ⇒ Object


130
131
132
133
134
# File 'app/models/topic.rb', line 130

def pull_follower(uid)
  return false if uid == user_id
  pull(follower_ids: uid)
  true
end

#push_follower(uid) ⇒ Object


123
124
125
126
127
128
# File 'app/models/topic.rb', line 123

def push_follower(uid)
  return false if uid == user_id
  return false if followed?(uid)
  push(follower_ids: uid)
  true
end

#reply_idsObject

所有的回复编号


172
173
174
175
176
# File 'app/models/topic.rb', line 172

def reply_ids
  Rails.cache.fetch([self, 'reply_ids']) do
    self.replies.order('id asc').pluck(:id)
  end
end

#store_cache_fieldsObject


92
93
94
# File 'app/models/topic.rb', line 92

def store_cache_fields
  self.node_name = node.try(:name) || ''
end

#update_deleted_last_reply(deleted_reply) ⇒ Object

更新最后更新人,当最后个回帖删除的时候


151
152
153
154
155
156
157
# File 'app/models/topic.rb', line 151

def update_deleted_last_reply(deleted_reply)
  return false if deleted_reply.blank?
  return false if last_reply_user_id != deleted_reply.user_id

  previous_reply = replies.where.not(id: deleted_reply.id).recent.first
  update_last_reply(previous_reply, force: true)
end

#update_last_reply(reply, opts = {}) ⇒ Object


136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'app/models/topic.rb', line 136

def update_last_reply(reply, opts = {})
  # replied_at 用于最新回复的排序,如果帖着创建时间在一个月以前,就不再往前面顶了
  return false if reply.blank? && !opts[:force]

  self.last_active_mark = Time.now.to_i if created_at > 1.month.ago
  self.replied_at = reply.try(:created_at)
  self.last_reply_id = reply.try(:id)
  self.last_reply_user_id = reply.try(:user_id)
  self. = reply.try(:user_login)
  # Reindex Search document
  SearchIndexer.perform_later('update', 'topic', self.id)
  save
end