백로그
0할 일
1User 모델 확장 — 마이그레이션 + enum + 메서드 + 테스트
## 목표 PRD Section 8.1 기반 users 테이블 확장 및 User 모델 구현. ## 현재 상태 - users 테이블: email_address, name, password_digest만 존재 - User 모델: has_secure_password, sessions 연관, email normalizes ## 마이그레이션 생성 (PRD Section 8.1) ``` add_column :users, :nickname, :string add_column :users, :avatar_url, :string add_column :users, :role, :integer, default: 0, null: false add_column :users, :nineways_uid, :string add_column :users, :nineways_strength_type, :string add_column :users, :nineways_dna_traits, :jsonb, default: {} add_column :users, :nineways_synced_at, :datetime add_column :users, :onboarding_goal, :integer, default: 0 add_column :users, :dev_level, :integer, default: 0 add_column :users, :onboarding_completed, :boolean, default: false add_column :users, :streak_days, :integer, default: 0 add_column :users, :last_active_at, :datetime add_column :users, :total_xp, :integer, default: 0 add_index :users, :nineways_uid add_index :users, :role ``` ## User 모델 확장 ```ruby enum :role, { free: 0, cohort: 1, admin: 2 } enum :onboarding_goal, { saas: 0, side_income: 1, portfolio: 2, validation: 3 } enum :dev_level, { none: 0, basic: 1, intermediate: 2, developer: 3 } # 연관 (현재 단계에서 추가 가능한 것만 — 다른 테이블은 아직 없음) has_many :cohort_applications, dependent: :destroy # 아직 테이블 없으나 선언만 def toss_customer_key = "valueit-user-#{id}" def can_access?(feature_level) case feature_level when :free then true when :cohort then role.in?(%w[cohort admin]) when :admin then admin? end end ``` ## ⚠️ 주의 - 기존 `email_address` 컬럼명 유지 (PRD의 `email`과 다름 — Rails 8 auth generator가 email_address로 생성) - 기존 normalizes, validates 유지 - 아직 없는 테이블(projects, cohort_applications 등)의 has_many는 추가하지 않거나, 존재하지 않는 테이블 참조 시 에러나지 않도록 주의 ## 테스트 (TDD) - role enum 동작 (free/cohort/admin) - onboarding_goal enum 동작 - dev_level enum 동작 - can_access?(:free) → 모든 유저 true - can_access?(:cohort) → cohort/admin만 true - can_access?(:admin) → admin만 true - toss_customer_key 포맷 확인 - fixture 업데이트 ## 완료 기준 - bin/rails db:migrate 성공 - 모델 테스트 전체 통과 - 기존 테스트 깨지지 않음