/
Dmitry-F
/
cbt_tool
Обзор
Документация
Войти
/
Dmitry-F
/
cbt_tool
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
python-ml-service
app/models/session.rb
110 строк
3 KB
Dmitriy-Filatov
fix: обновление счётчиков в реальном времени
20 мар 2026, 16:47
20 мар 2026, 16:47
beb487f
Код
Авторство
О чём код?
# == Schema Information # # Table name: sessions # # id :bigint not null, primary key # homework :text # notes :text # session_date :date # topic :string # created_at :datetime not null # updated_at :datetime not null # client_id :bigint not null # therapist_id :bigint not null # class Session < ApplicationRecord # ===== Связи ===== belongs_to :therapist belongs_to :client, counter_cache: true # ===== Валидации ===== validates :session_date, presence: true validates :topic, presence: { message: "Тема сессии не может быть пустой" } validate :no_overlapping_sessions, if: :therapist_id_and_date_present? # ===== Скоупы ===== scope :ordered, -> { order(session_date: :desc, created_at: :desc) } scope :for_therapist, ->(therapist_id) { where(therapist_id: therapist_id) } scope :for_client, ->(client_id) { where(client_id: client_id) } scope :today, -> { where(session_date: Date.current) } scope :upcoming, -> { where("session_date >= ?", Date.current).order(session_date: :asc) } scope :past, -> { where("session_date < ?", Date.current).order(session_date: :desc) } # ===== ПОЛНОТЕКСТОВЫЙ ПОИСК (FTS) ===== scope :search, ->(query) { return all if query.blank? quoted_query = connection.quote(query) where("search_vector @@ websearch_to_tsquery('russian', ?)", query) .order(Arel.sql("ts_rank(search_vector, websearch_to_tsquery('russian', #{quoted_query})) DESC")) } # ===== Коллбэки ===== after_commit :broadcast_session_changes, on: [ :create, :update ] after_destroy_commit :broadcast_session_removal # ===== Hotwire / Turbo Streams ===== def broadcast_session_changes # ОБНОВЛЯЕМ СЧЁТЧИК НА ЛЕВОЙ ПАНЕЛИ Turbo::StreamsChannel.broadcast_update_to( "client_#{client_id}_dashboard", target: "sessions_count", html: client.reload.sessions_count.to_s ) # Остальной код (prepend/replace) if previous_changes.key?("id") broadcast_prepend_to( "therapist_#{therapist_id}_sessions", target: "sessions_list", partial: "sessions/session", locals: { session: self } ) broadcast_prepend_to( "client_#{client_id}_sessions", target: "sessions_list", partial: "sessions/session", locals: { session: self } ) else broadcast_replace_to( "therapist_#{therapist_id}_sessions", target: "session_#{id}", partial: "sessions/session", locals: { session: self } ) broadcast_replace_to( "client_#{client_id}_sessions", target: "session_#{id}", partial: "sessions/session", locals: { session: self } ) end end def broadcast_session_removal broadcast_remove_to( "therapist_#{therapist_id}_sessions", target: "session_#{id}" ) broadcast_remove_to( "client_#{client_id}_sessions", target: "session_#{id}" ) end private def therapist_id_and_date_present? therapist_id.present? && session_date.present? end def no_overlapping_sessions existing = Session.where(therapist_id: therapist_id, session_date: session_date) existing = existing.where.not(id: id) if persisted? if existing.exists? errors.add(:session_date, "У вас уже есть сессия на эту дату") end end end