aboutsummaryrefslogtreecommitdiffstats
path: root/app/models/discussion.rb
blob: cc1da7a1b26c5e692cb0189b165483dbdbea8d3f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
class Discussion < ActiveRecord::Base
  attr_accessor :recipient_tokens, :recipient_ids
  attr_reader :recipient_ids

  # paginates_per 10

  # создатель
  has_many :messages, :dependent => :destroy

  # участники
  has_many :speakers, :dependent => :destroy
  has_many :users, :through => :speakers

  # отметки о прочтении юзеров
  # has_many :views, :dependent => :destroy, :class_name => "DiscussionView"

  # жутко неоптимизированная часть, возможны баги
  # scope :unread_for, lambda { |user_or_user_id| joins(:views, :speakers).where("discussions.updated_at >= discussion_views.updated_at AND speakers.user_id = ?", user_or_user_id.is_a?(User) ? user_or_user_id.id : user_or_user_id ) }

  accepts_nested_attributes_for :messages

  validate :check_that_has_at_least_two_users # не даем создать дискуссию, у которой нет получателей

  # добавляем записи об указанных собеседников
  after_save(:on => :create) do
    Rails.logger.info("Repicients ids: #{recipient_ids.inspect}")

    if recipient_ids.kind_of?(Array)
      recipient_ids.uniq!
      recipient_ids.each do |id|
        recipient = User.find(id)
        add_speaker(recipient) if recipient
      end
    end
  end

  def recipient_tokens=(ids)
    self.recipient_ids = ids
  end

  def add_recipient_token id
    self.recipient_ids << id if self.recipient_ids
  end

  def add_speaker(user)
    raise ArgumentError, "You can add speaker only to existing Discussion. Save your the Discussion object firstly" if new_record?
    Speaker.create(:discussion => self, :user => user)
  end

  def remove_speaker(user)
    speaker = find_speaker_by_user(user)
    speaker.destroy if speaker
  end

  def user_invited_at(user)
    speaker = find_speaker_by_user(user)
    speaker.created_at
  end

  def can_participate?(user)
    speaker = find_speaker_by_user(user)
    speaker ? true : false
  end

  # проверяет, есть ли уже беседа между пользователями
  # TODO вынести в отдельный метод а в этом возращать true/false, а то неправославно как-то
  def self.find_between_users(user, user2)
    dialog = nil
    discussions = self.joins(:speakers).includes(:users).where("speakers.user_id = ?", user.id)
    Rails.logger.info "Searching for ids: #{user.id}, #{user2.id}"
    discussions.each do |discussion|
      dialog = discussion if discussion.private? && ((discussion.users.first == user && discussion.users.last == user2) || (discussion.users.first == user2 && discussion.users.last == user))
    end
    dialog
  end

  # приватная/групповая
  def private?
    self.users.size <= 2
  end

  # дата последнего сообщения в дискуссии
  def last_message_at
    self.messages.last ? self.messages.last.created_at : nil
  end

  # проверка, является ли дискуссия непрочитанной для пользователя
  def unread_for?(user)
    flag = self.views.find_by_user_id(user.id)
    if flag
      self.updated_at >= flag.updated_at
    else
      true
    end
  end

  # пометить как прочитанная
  def mark_as_read_for(user)
    true
  #   flag = DiscussionView.find_or_create_by_user_id_and_discussion_id(user.id, self.id)
  #   flag.touch
  end

  private

  def find_speaker_by_user user
    Speaker.find_by_discussion_id_and_user_id(self.id, user.id)
  end

  def check_that_has_at_least_two_users
    Rails.logger.info self.recipient_ids
    errors.add :recipient_tokens, "Укажите хотя бы одного получателя" if !self.recipient_ids || self.recipient_ids.size < 2
  end

end