Merge pull request #2 from turniere/ticket/TURNIERE-71

Implement database schema, matching models and specs
This commit is contained in:
Thor77 2018-11-19 17:05:50 +01:00 committed by GitHub
commit feee3f9378
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 357 additions and 68 deletions

View File

@ -1 +1,4 @@
fail_on_violations: true
ruby:
config_file: .rubocop.yml

View File

@ -30,3 +30,16 @@ Metrics/AbcSize:
Exclude:
- "db/migrate/*"
Max: 20
Metrics/BlockLength:
ExcludedMethods:
- "namespace"
- "create_table"
Exclude:
- "config/**/*.rb"
- "spec/**/*.rb"
# Disable documentation checks for now
# should be done with yard instead
Style/Documentation:
Enabled: false

View File

@ -1,6 +1,7 @@
# frozen_string_literal: true
class Group < ApplicationRecord
belongs_to :matches
belongs_to :teams
belongs_to :stage
has_many :matches, dependent: :destroy
has_many :group_scores, dependent: :destroy
end

View File

@ -0,0 +1,6 @@
# frozen_string_literal: true
class GroupScore < ApplicationRecord
belongs_to :team
belongs_to :group
end

View File

@ -1,4 +0,0 @@
# frozen_string_literal: true
class GroupStage < ApplicationRecord
end

View File

@ -1,4 +1,9 @@
# frozen_string_literal: true
class Match < ApplicationRecord
belongs_to :stage
belongs_to :group
has_many :scores, dependent: :destroy
validates :scores, length: { maximum: 2 }
end

View File

@ -1,4 +0,0 @@
# frozen_string_literal: true
class PlayoffStage < ApplicationRecord
end

6
app/models/score.rb Normal file
View File

@ -0,0 +1,6 @@
# frozen_string_literal: true
class Score < ApplicationRecord
belongs_to :match
belongs_to :team
end

7
app/models/stage.rb Normal file
View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class Stage < ApplicationRecord
belongs_to :tournament
has_many :matches, dependent: :destroy
has_many :groups, dependent: :destroy
end

View File

@ -1,4 +1,9 @@
# frozen_string_literal: true
class Team < ApplicationRecord
belongs_to :tournament
has_many :group_scores, dependent: :destroy
has_many :scores, dependent: :destroy
validates :name, presence: true
end

View File

@ -1,4 +1,18 @@
# frozen_string_literal: true
require 'securerandom'
class Tournament < ApplicationRecord
belongs_to :user
has_many :teams, dependent: :destroy
has_many :stages, dependent: :destroy
validates :name, presence: true
validates :code, presence: true, uniqueness: true
alias_attribute :owner, :user
after_initialize do |tournament|
tournament.code ||= SecureRandom.hex 3
end
end

View File

@ -7,4 +7,6 @@ class User < ApplicationRecord
include DeviseTokenAuth::Concerns::User
validates :username, presence: true, uniqueness: true
has_many :tournaments, dependent: :destroy
end

View File

@ -2,62 +2,16 @@
class CreateSchema < ActiveRecord::Migration[5.2]
def change
create_table :groups do |t|
t.string :name
t.timestamps
end
create_table :group_stages do |t|
t.integer :playoff_size
t.timestamps
end
create_table :matches do |t|
t.integer :score_team_1
t.integer :score_team_2
t.integer :state
t.integer :position
t.boolean :is_group_match
t.timestamps
end
create_table :playoff_stages do |t|
t.integer :level
t.timestamps
end
create_table :teams do |t|
t.string :name
t.integer :group_score
t.integer :group_points_scored
t.integer :group_points_recieved
t.timestamps
end
create_table :tournaments do |t|
t.string :name
t.string :code
t.string :description
t.boolean :public, default: true
t.timestamps
end
create_table :users do |t|
## Required
t.string :provider, null: false, default: 'email'
t.string :uid, null: false, default: ''
t.string :provider, null: false, default: 'email', index: true
t.string :uid, null: false, default: '', index: { unique: true }
## Database authenticatable
t.string :encrypted_password, null: false, default: ''
## Recoverable
t.string :reset_password_token
t.string :reset_password_token, index: { unique: true }
t.datetime :reset_password_sent_at
t.boolean :allow_password_change, default: false
@ -72,7 +26,7 @@ class CreateSchema < ActiveRecord::Migration[5.2]
t.string :last_sign_in_ip
## Confirmable
t.string :confirmation_token
t.string :confirmation_token, index: { unique: true }
t.datetime :confirmed_at
t.datetime :confirmation_sent_at
t.string :unconfirmed_email # Only if using reconfirmable
@ -83,8 +37,8 @@ class CreateSchema < ActiveRecord::Migration[5.2]
# t.datetime :locked_at
## User Info
t.string :username
t.string :email
t.string :username, index: { unique: true }
t.string :email, index: { unique: true }
## Tokens
t.text :tokens
@ -92,11 +46,69 @@ class CreateSchema < ActiveRecord::Migration[5.2]
t.timestamps
end
add_index :users, :username, unique: true
add_index :users, :email, unique: true
add_index :users, %i[uid provider], unique: true
add_index :users, :reset_password_token, unique: true
add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
create_table :tournaments do |t|
t.string :name, null: false
t.string :code, null: false, index: { unique: true }
t.string :description
t.boolean :public, default: true
# relation to owner
t.belongs_to :user, index: true, null: false, foreign_key: { on_delete: :cascade }
t.timestamps
end
create_table :stages do |t|
t.integer :level
t.belongs_to :tournament, index: true, foreign_key: { on_delete: :cascade }, null: false
t.timestamps
end
create_table :groups do |t|
t.integer :number
t.belongs_to :stage, index: true, foreign_key: { on_delete: :cascade }, null: false
t.timestamps
end
create_table :matches do |t|
t.integer :state, default: 0
t.belongs_to :stage, index: true, foreign_key: { on_delete: :cascade }
t.belongs_to :group, index: true, foreign_key: { on_delete: :cascade }
t.timestamps
end
create_table :teams do |t|
t.string :name
t.belongs_to :tournament, index: true, foreign_key: { on_delete: :cascade }
t.timestamps
end
create_table :scores do |t|
t.integer :score, default: 0
t.belongs_to :match, index: true, null: false, foreign_key: { on_delete: :cascade }
t.belongs_to :team, index: true, null: false, foreign_key: { on_delete: :cascade }
t.timestamps
end
create_table :group_scores do |t|
t.integer :score, default: 0
t.integer :points_scored, default: 0
t.integer :points_received, default: 0
t.belongs_to :team, index: true, foreign_key: { on_delete: :cascade }, null: false
t.belongs_to :group, index: true, foreign_key: { on_delete: :cascade }, null: false
t.timestamps
end
end
end

View File

@ -0,0 +1,8 @@
# frozen_string_literal: true
FactoryBot.define do
factory :group_score do
team
group
end
end

8
spec/factories/groups.rb Normal file
View File

@ -0,0 +1,8 @@
# frozen_string_literal: true
FactoryBot.define do
factory :group do
number { 0 }
stage
end
end

View File

@ -0,0 +1,8 @@
# frozen_string_literal: true
FactoryBot.define do
factory :match do
stage
group
end
end

9
spec/factories/scores.rb Normal file
View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
FactoryBot.define do
factory :score do
score { 0 }
match
team
end
end

7
spec/factories/stages.rb Normal file
View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
FactoryBot.define do
factory :stage do
tournament
end
end

8
spec/factories/teams.rb Normal file
View File

@ -0,0 +1,8 @@
# frozen_string_literal: true
FactoryBot.define do
factory :team do
name { Faker::Dog.name }
tournament
end
end

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
FactoryBot.define do
factory :tournament do
name { Faker::Dog.name }
description { Faker::Lorem.sentence }
user
end
end

8
spec/factories/users.rb Normal file
View File

@ -0,0 +1,8 @@
# frozen_string_literal: true
FactoryBot.define do
factory :user do
username { Faker::Internet.username }
email { Faker::Internet.email }
end
end

View File

@ -0,0 +1,14 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe GroupScore, type: :model do
describe 'association' do
it { should belong_to :team }
it { should belong_to :group }
end
it 'has a valid factory' do
expect(build(:group_score)).to be_valid
end
end

15
spec/models/group_spec.rb Normal file
View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Group, type: :model do
describe 'association' do
it { should belong_to :stage }
it { should have_many :matches }
it { should have_many :group_scores }
end
it 'has a valid factory' do
expect(build(:group)).to be_valid
end
end

32
spec/models/match_spec.rb Normal file
View File

@ -0,0 +1,32 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Match, type: :model do
context 'association' do
it { should have_many :scores }
it { should belong_to :stage }
it { should belong_to :group }
end
context 'scores' do
before do
@match = create(:match)
@match.scores << build_pair(:score)
end
it 'can only have two scores' do
@match.scores << build(:score)
expect(@match).to be_invalid
end
it 'can access its scores' do
@match.scores[0].score = 0
@match.scores[1].score = 0
end
end
it 'has a valid factory' do
expect(build(:match)).to be_valid
end
end

14
spec/models/score_spec.rb Normal file
View File

@ -0,0 +1,14 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Score, type: :model do
describe 'association' do
it { should belong_to :match }
it { should belong_to :team }
end
it 'has a valid factory' do
expect(build(:score)).to be_valid
end
end

15
spec/models/stage_spec.rb Normal file
View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Stage, type: :model do
describe 'association' do
it { should belong_to :tournament }
it { should have_many :matches }
it { should have_many :groups }
end
it 'has a valid factory' do
expect(build(:stage)).to be_valid
end
end

19
spec/models/team_spec.rb Normal file
View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Team, type: :model do
describe 'validation' do
it { should validate_presence_of :name }
end
describe 'association' do
it { should belong_to :tournament }
it { should have_many :group_scores }
it { should have_many :scores }
end
it 'has a valid factory' do
expect(build(:team)).to be_valid
end
end

View File

@ -0,0 +1,36 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe Tournament, type: :model do
before do
@tournament = create(:tournament)
end
describe 'validation' do
it { should validate_presence_of :name }
it { should validate_presence_of :code }
it { should validate_uniqueness_of :code }
it { should_not validate_presence_of :description }
it { should_not validate_presence_of :public }
end
describe 'initialization' do
it 'should have a code' do
expect(@tournament.code.length).to be(6)
end
it 'should be public' do
expect(@tournament.public).to be(true)
end
end
describe 'association' do
it { should belong_to :user }
it { should have_many :teams }
it { should have_many :stages }
end
it 'has valid factory' do
expect(build(:tournament)).to be_valid
end
end

13
spec/models/user_spec.rb Normal file
View File

@ -0,0 +1,13 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe User, type: :model do
describe 'association' do
it { should have_many :tournaments }
end
it 'has a valid factory' do
expect(build(:user)).to be_valid
end
end