Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,8 @@ GEM
racc (~> 1.4)
nokogiri (1.18.8-arm64-darwin)
racc (~> 1.4)
nokogiri (1.18.8-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.18.8-x86_64-linux-gnu)
racc (~> 1.4)
nokogiri (1.18.8-x86_64-linux-musl)
Expand Down Expand Up @@ -375,12 +377,14 @@ GEM
tailwindcss-ruby (4.1.11-aarch64-linux-gnu)
tailwindcss-ruby (4.1.11-aarch64-linux-musl)
tailwindcss-ruby (4.1.11-arm64-darwin)
tailwindcss-ruby (4.1.11-x86_64-darwin)
tailwindcss-ruby (4.1.11-x86_64-linux-gnu)
tailwindcss-ruby (4.1.11-x86_64-linux-musl)
thor (1.3.2)
thruster (0.1.14)
thruster (0.1.14-aarch64-linux)
thruster (0.1.14-arm64-darwin)
thruster (0.1.14-x86_64-darwin)
thruster (0.1.14-x86_64-linux)
timeout (0.4.3)
tzinfo (2.0.6)
Expand Down Expand Up @@ -412,6 +416,7 @@ PLATFORMS
arm-linux-gnu
arm-linux-musl
arm64-darwin-24
x86_64-darwin-23
x86_64-linux
x86_64-linux-gnu
x86_64-linux-musl
Expand Down
5 changes: 5 additions & 0 deletions app/models/chat.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Chat < ApplicationRecord
belongs_to :repository, optional: true

validates :chat_type, presence: true, inclusion: { in: %w[private group] }
end
9 changes: 9 additions & 0 deletions app/models/chat_user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class ChatUser < ApplicationRecord
belongs_to :chat
belongs_to :user
belongs_to :last_read_message, class_name: "Message", optional: true

validates :chat_id, presence: true
validates :user_id, presence: true
validates :chat_id, uniqueness: { scope: :user_id }
end
8 changes: 8 additions & 0 deletions app/models/message.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class Message < ApplicationRecord
belongs_to :chat
belongs_to :user

validates :chat_id, presence: true
validates :user_id, presence: true
validates :content, presence: true, length: { maximum: 400 }
end
8 changes: 8 additions & 0 deletions app/models/repository.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class Repository < ApplicationRecord
has_many :user_repositories
has_many :users, through: :user_repositories

validates :github_repo_id, presence: true, uniqueness: true
validates :name, presence: true
validates :url, presence: true
end
8 changes: 8 additions & 0 deletions app/models/user_repository.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class UserRepository < ApplicationRecord
belongs_to :user
belongs_to :repository

validates :user_id, presence: true
validates :repository_id, presence: true
validates :user_id, uniqueness: { scope: :repository_id }
end
12 changes: 12 additions & 0 deletions db/migrate/20250724201343_create_repositories.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class CreateRepositories < ActiveRecord::Migration[8.0]
def change
create_table :repositories do |t|
t.bigint :github_repo_id
t.string :name
t.string :url

t.timestamps
end
add_index :repositories, :url, unique: true
end
end
11 changes: 11 additions & 0 deletions db/migrate/20250724201842_create_user_repositories.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class CreateUserRepositories < ActiveRecord::Migration[8.0]
def change
create_table :user_repositories do |t|
t.references :user, null: false, foreign_key: true
t.references :repository, null: false, foreign_key: true

t.timestamps
end
add_index :user_repositories, [ :user_id, :repository_id ], unique: true
end
end
10 changes: 10 additions & 0 deletions db/migrate/20250724202204_create_chats.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class CreateChats < ActiveRecord::Migration[8.0]
def change
create_table :chats do |t|
t.string :chat_type
t.references :repository, null: true, foreign_key: true

t.timestamps
end
end
end
12 changes: 12 additions & 0 deletions db/migrate/20250724202621_create_messages.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class CreateMessages < ActiveRecord::Migration[8.0]
def change
create_table :messages do |t|
t.references :chat, null: false, foreign_key: true
t.references :user, null: false, foreign_key: true
t.string :content, limit: 400

t.timestamps
end
add_index :messages, [ :chat_id, :created_at ]
end
end
12 changes: 12 additions & 0 deletions db/migrate/20250724202955_create_chat_users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class CreateChatUsers < ActiveRecord::Migration[8.0]
def change
create_table :chat_users do |t|
t.references :chat, null: false, foreign_key: true
t.references :user, null: false, foreign_key: true
t.references :last_read_message, null: true, foreign_key: { to_table: :messages }

t.timestamps
end
add_index :chat_users, [ :chat_id, :user_id ], unique: true
end
end
61 changes: 60 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions memory-bank/activeContext.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

## Ключевые архитектурные решения
- **Модель данных**: Семь основных таблиц для хранения данных о пользователях, репозиториях, чатах и сообщениях
- **Отслеживание прочитанных сообщений**: Принято решение не создавать отдельную модель UnreadMessage. Вместо этого статус прочтения реализуется через поле last_read_message_id в таблице chat_users. Это упрощает схему, уменьшает количество таблиц и соответствует текущим требованиям (один маркер прочтения на пользователя в чате). Если в будущем потребуется более сложная логика (например, несколько маркеров или аналитика по ушедшим пользователям), можно будет рассмотреть отдельную таблицу.
- **Интеграция с GitHub**: Синхронизация данных при входе пользователя
- **Автоматическое создание чатов**: На основе общих приватных репозиториев
- **Реализация интерфейса**: Hotwire (Turbo, Stimulus) для динамического обновления без полной перезагрузки страницы
Expand Down
21 changes: 5 additions & 16 deletions memory-bank/diagrams/database_schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ erDiagram
bigint id PK
bigint github_repo_id UK "Уникальный"
string name "Не null"
boolean private "Не null"
string url "Не null"
datetime created_at
datetime updated_at
}
Expand All @@ -41,16 +41,6 @@ erDiagram
datetime updated_at
}

CHAT_USERS {
bigint id PK
bigint chat_id FK
bigint user_id FK
datetime joined_at
datetime left_at "Nullable"
datetime created_at
datetime updated_at
}

MESSAGES {
bigint id PK
bigint chat_id FK
Expand All @@ -59,11 +49,12 @@ erDiagram
datetime created_at
}

UNREAD_MESSAGES {
CHAT_USERS {
bigint id PK
bigint user_id FK
bigint chat_id FK
bigint user_id FK
bigint last_read_message_id FK "Nullable"
datetime created_at
datetime updated_at
}

Expand All @@ -74,7 +65,5 @@ erDiagram
CHATS ||--o{ CHAT_USERS : "включает"
USERS ||--o{ MESSAGES : "отправляет"
CHATS ||--o{ MESSAGES : "содержит"
USERS ||--o{ UNREAD_MESSAGES : "имеет"
CHATS ||--o{ UNREAD_MESSAGES : "имеет"
MESSAGES ||--o{ UNREAD_MESSAGES : "отмечает"
CHAT_USERS ||--o{ MESSAGES : "читает"
```
62 changes: 61 additions & 1 deletion memory-bank/progress.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
- **Проверка зависимостей**: Выявлены отсутствующие гемы (OmniAuth, Tailwind, Hotwire)
- **Проверка конфигурации**: Структура проекта соответствует требованиям
- **Проверка окружения**: Окружение готово для разработки
- **Рекомендации**:
- **Рекомендации**:
- Добавить недостающие гемы в Gemfile
- Обновить план реализации с учетом Action Cable и Sidekiq
- Оптимизировать схему базы данных (индексы, дополнительные поля)
Expand Down Expand Up @@ -99,3 +99,63 @@
- [ ] Переход в режим BUILD
- [ ] Реализация базовой функциональности
- [ ] Архивирование задачи

## План реализации моделей (TDD)

### Общий подход
- Следуем принципам TDD: сначала пишем тесты, затем миграции и реализацию моделей, после чего рефакторим и повторяем цикл.
- Для каждой модели: Repository, UserRepository, Chat, Message, ChatUser (с last_read_message_id).

### Этапы для каждой модели
1. Написать тесты для валидаций, ассоциаций и бизнес-логики.
2. Создать миграцию для таблицы и необходимых индексов.
3. Реализовать модель с ассоциациями, валидациями и методами.
4. Запустить тесты и убедиться, что всё работает корректно.

### Порядок реализации
1. Repository
2. UserRepository
3. Chat
4. Message
5. ChatUser (с полем last_read_message_id)

### Интеграция и тесты взаимодействия
- После реализации всех моделей — интеграционные тесты для сценариев взаимодействия (создание чата, отправка сообщения, отслеживание прочтения и т.д.).
- Проверка edge-case сценариев (выход пользователя из чата, удаление сообщений и т.д.).

### Рефакторинг и документация
- Рефакторинг моделей и тестов для соответствия best practices.
- Документирование связей и бизнес-логики моделей.

## Рефлексия по реализации моделей

- Все требования к структуре моделей, валидациям и ассоциациям выполнены.
- Все модели покрыты юнит-тестами, все тесты проходят (TDD соблюден).
- Интеграционные и функциональные тесты на этом этапе не требуются, так как реализованы только модели.
- Ключевые архитектурные решения:
- Отслеживание прочтения сообщений реализовано через поле last_read_message_id в chat_users (вместо отдельной таблицы). Это решение выбрано для простоты и производительности MVP, а также чтобы избежать избыточных таблиц. Отдельная таблица может понадобиться только при усложнении логики (например, для аналитики или нескольких маркеров прочтения).
- В таблице repositories убрано поле private (все репозитории по проекту приватные), добавлено поле url для прямой ссылки на GitHub.
- В таблицах chat_users и chats реализованы только необходимые для MVP поля.
- Все изменения и упрощения были сделаны для минимизации схемы и ускорения MVP, с возможностью расширения в будущем.
- Следующий этап — реализация бизнес-логики и сервисных объектов, после чего появится необходимость в интеграционных тестах.

## ARCHIVE: Изменения в модели (before/after)

### До изменений
- Не было моделей Repository, UserRepository, Chat, Message, ChatUser (кроме User).
- Не было таблиц и миграций для этих сущностей.
- Не было логики отслеживания непрочитанных сообщений.
- Не было тестов и ассоциаций для чатов и сообщений.
- В схеме БД были избыточные поля и таблицы (например, unread_messages, поле private в repositories).

### После изменений
- **Repository**: добавлены модель, миграция, тесты; поля: github_repo_id, name, url, timestamps; ассоциации: has_many :user_repositories, has_many :users, through: :user_repositories; убрано поле private, добавлено url.
- **UserRepository**: добавлены модель, миграция, тесты; поля: user_id, repository_id, timestamps; ассоциации: belongs_to :user, belongs_to :repository; уникальный индекс.
- **Chat**: добавлены модель, миграция, тесты; поля: chat_type (private/group), repository_id (nullable), timestamps; ассоциация: belongs_to :repository, optional: true.
- **Message**: добавлены модель, миграция, тесты; поля: chat_id, user_id, content (max 400), timestamps; ассоциации: belongs_to :chat, belongs_to :user; индекс для истории чата.
- **ChatUser**: добавлены модель, миграция, тесты; поля: chat_id, user_id, last_read_message_id (nullable), timestamps; ассоциации: belongs_to :chat, belongs_to :user, belongs_to :last_read_message, class_name: 'Message', optional: true; уникальный индекс; отслеживание прочтения через last_read_message_id.
- Все модели покрыты юнит-тестами (валидации и ассоциации), TDD соблюден.
- Схема упрощена: убраны избыточные поля и таблицы, оставлены только необходимые для MVP.
- Документация и диаграммы обновлены.

**Модельный слой завершён и заархивирован.**
15 changes: 8 additions & 7 deletions memory-bank/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,16 +160,17 @@
- [x] Настройка OmniAuth для GitHub
- [ ] Настройка Sidekiq

- [ ] **Разработка моделей и миграций**
- [x] **Разработка моделей и миграций**
- [x] Модель User
- [ ] Модель Repository
- [ ] Модель UserRepository
- [ ] Модель Chat
- [ ] Модель ChatUser
- [ ] Модель Message
- [ ] Модель UnreadMessage
- [x] Модель Repository
- [x] Модель UserRepository
- [x] Модель Chat
- [x] Модель Message
- [x] Модель ChatUser (добавить поле last_read_message_id для отслеживания прочитанных сообщений)
- [ ] Оптимизированные индексы

# Модельный слой завершён и заархивирован.

- [x] **Проектирование интерфейса**
- [x] Разработка дизайн-системы (выбран GitHub-inspired Design System)
- [x] Проектирование процесса аутентификации (выбран одностраничный процесс с информационными элементами)
Expand Down
Loading