From e8c3f045779ccf3f6eb1b33c5939cc8de20edc09 Mon Sep 17 00:00:00 2001 From: sto Date: Sat, 22 Mar 2025 18:52:20 +0100 Subject: [PATCH] Public scoreboard scaffold --- app/controllers/application_controller.rb | 4 ++++ app/controllers/contests_controller.rb | 14 ++++++++++++++ app/models/contest.rb | 2 +- app/policies/contest_policy.rb | 4 ++++ app/views/contests/scoreboard.html.slim | 18 ++++++++++++++++++ app/views/contests/show.html.slim | 2 +- config/routes.rb | 2 ++ 7 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 app/views/contests/scoreboard.html.slim diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 46cf21b..e897995 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -26,4 +26,8 @@ class ApplicationController < ActionController::Base flash[:error] = t "#{policy_name}.#{exception.query}", scope: "pundit", default: :default redirect_back_or_to(root_path) end + + def not_found + render file: "#{Rails.root}/public/404.html", layout: false, status: :not_found + end end diff --git a/app/controllers/contests_controller.rb b/app/controllers/contests_controller.rb index a3d9ad1..44c55cd 100644 --- a/app/controllers/contests_controller.rb +++ b/app/controllers/contests_controller.rb @@ -56,6 +56,20 @@ class ContestsController < ApplicationController authorize @contest end + def scoreboard + @contest = Contest.find_by(slug: params[:id]) + unless @contest + skip_authorization + not_found and return + end + authorize @contest + + @title = @contest.name + @contestants = @contest.contestants.order(:name) + @puzzles = @contest.puzzles.order(:id) + render :scoreboard + end + private def set_badges diff --git a/app/models/contest.rb b/app/models/contest.rb index 3bda000..5b6fa87 100644 --- a/app/models/contest.rb +++ b/app/models/contest.rb @@ -27,5 +27,5 @@ class Contest < ApplicationRecord has_many :puzzles, dependent: :destroy validates :name, presence: true - validates :slug, presence: true, format: { with: /\A(\w|-)*\z/, message: 'Only alphanumeric characters, "-" and "_" allowed.' } + validates :slug, presence: true, uniqueness: true, format: { with: /\A(\w|-)*\z/, message: 'Only alphanumeric characters, "-" and "_" allowed.' } end diff --git a/app/policies/contest_policy.rb b/app/policies/contest_policy.rb index d6a9d0a..c71a77c 100644 --- a/app/policies/contest_policy.rb +++ b/app/policies/contest_policy.rb @@ -26,4 +26,8 @@ class ContestPolicy < ApplicationPolicy def destroy? record.user.id == user.id || user.admin? end + + def scoreboard? + true + end end diff --git a/app/views/contests/scoreboard.html.slim b/app/views/contests/scoreboard.html.slim new file mode 100644 index 0000000..d1615ea --- /dev/null +++ b/app/views/contests/scoreboard.html.slim @@ -0,0 +1,18 @@ +table.table.table-striped.table-hover + thead + tr + th scope="col" + | Rank + th scope="col" + | Name + th scope="col" + | Completed puzzles + tbody + - @contestants.each_with_index do |contestant, index| + tr scope="row" + td + = index + 1 + td + = contestant.name + td + = contestant.completions.length \ No newline at end of file diff --git a/app/views/contests/show.html.slim b/app/views/contests/show.html.slim index cda8dc5..7aeb903 100644 --- a/app/views/contests/show.html.slim +++ b/app/views/contests/show.html.slim @@ -14,7 +14,7 @@ | Edit contest p |> Public scoreboard: - = link_to root_url + "public/#{@contest.slug}" + = link_to root_url + "public/#{@contest.slug}", root_url + "public/#{@contest.slug}" .row.mb-4 .col-6 diff --git a/config/routes.rb b/config/routes.rb index 4937488..73b87f1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -16,4 +16,6 @@ Rails.application.routes.draw do resources :passwords, param: :token resource :session resources :users + + get "public/:id", to: "contests#scoreboard" end