Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plug Batch info on Kitt callback and move back City on User to simplify validation logic. #325

Merged
merged 11 commits into from
Nov 17, 2023
4 changes: 2 additions & 2 deletions app/components/user_form_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@

<div class="flex flex-col gap-y-1 sm:flex-row sm:items-center sm:gap-x-3">
<%= f.label :batch_number, "Batch #" %>
<%= f.number_field :batch_number, value: @user.batch&.number, min: 1, class: "input", disabled: true %>
<%= f.number_field :batch_number, value: @user.batch&.number, min: 1, class: "input", disabled: @user.batch_id? %>
</div>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Le batch devrait toujours etre disabled.
Soit les gens en ont un et ils peuvent pas changer
Soit ils en ont pas et ils peuvent pas s'en rajouter un.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Soit ils en ont pas et ils peuvent pas s'en rajouter un.

J'avais pas cette info 😅 Je savais pas qu'on pouvait être "sans-batch", @pil0u on gère bien leurs points à eux ? Je me souviens plus de l'an dernier.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Aquaj Oui, on peut récupérer un batch 0 ou nil sur l'OAuth, des profs extérieurs par exemple, j'évalue à ~1000 Alumnis concernés quand j'ai lancé le scraper, donc pas négligeable.

Mais oui, on n'a plus de scoring par batch, uniquement par squad et campus. Et pour le campus, comme ils choisissent eux-mêmes parmi une liste existante, ils sont pris en compte 👍


<div class="flex flex-col gap-y-1 sm:flex-row sm:items-center sm:gap-x-3">
<%= f.label :city_name, "Campus" %>
wJoenn marked this conversation as resolved.
Show resolved Hide resolved
<%= f.collection_select(:city_id, City.order(:name), :id, :name, { prompt: "", selected: @user.batch&.city_id }, class: "input", disabled: @user.batch&.city_id?) %>
<%= f.collection_select(:city_id, City.order(:vanity_name), :id, :vanity_name, { prompt: "", selected: @user.city_id }, class: "input", disabled: @user.city_id?) %>
</div>

<div class="flex items-center gap-x-3 w-48 sm:w-fit">
Expand Down
11 changes: 3 additions & 8 deletions app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,18 +86,13 @@ def restrict_after_lock
end

def updated_params
batch = nil

if current_user.batch_id.nil? && form_params[:city_id] # rubocop:disable Style/IfUnlessModifier
batch = Batch.find_or_create_by(number: nil, city_id: form_params[:city_id])
end

{
accepted_coc: form_params[:accepted_coc],
aoc_id: form_params[:aoc_id],
entered_hardcore: form_params[:entered_hardcore],
username: form_params[:username],
batch_id: batch&.id,
batch_id: Batch.find_by(number: form_params[:batch_number])&.id,
city_id: form_params[:city_id],
referrer: User.find_by_referral_code(form_params[:referrer_code])
}.compact
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as previous comment, the batch should never be updated by the user event if he has none.

end
Expand All @@ -107,6 +102,6 @@ def unlock_achievements
end

def form_params
params.require(:user).permit(:accepted_coc, :aoc_id, :entered_hardcore, :username, :city_id, :referrer_code)
params.require(:user).permit(:accepted_coc, :aoc_id, :entered_hardcore, :username, :batch_number, :city_id, :referrer_code)
end
end
2 changes: 1 addition & 1 deletion app/models/batch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

class Batch < ApplicationRecord
has_many :users, dependent: :nullify
belongs_to :city
belongs_to :city, optional: true

validates :number, numericality: { in: 1...(2**31), message: "should be between 1 and 2^31" }, allow_nil: true
end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Si on garde une reference a city sur le batch alors je comprend pas comment un batch pourrait se retrouver sans city

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C'était surtout pour le système de choix de batch en cas de batch manquant sur Kitt. (Pcq du coup l'user choisirait un batch au choix, potentiellement un qu'on connaît pas et donc qui a pas de ville)

Mais si c'est pas nécessaire, je vais faire sauter ça.

37 changes: 31 additions & 6 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ class User < ApplicationRecord
CONTRIBUTORS = { pilou: "6788", aquaj: "449", louis: "19049", aurelie: "9168" }.freeze

belongs_to :batch, optional: true
belongs_to :city, optional: true
has_one :batch_city, through: :batch, source: :city
pil0u marked this conversation as resolved.
Show resolved Hide resolved
belongs_to :squad, optional: true, touch: true
belongs_to :referrer, class_name: "User", optional: true

delegate :city, :city_id, to: :batch, allow_nil: true

has_many :completions, dependent: :destroy
has_many :user_day_scores, class_name: "Cache::UserDayScore", dependent: :delete_all
has_many :solo_points, class_name: "Cache::SoloPoint", dependent: :delete_all
Expand All @@ -28,6 +28,8 @@ class User < ApplicationRecord
validates :username, presence: true

validate :not_referring_self
validate :not_changing_cities
validate :city_must_match_batch

scope :admins, -> { where(uid: ADMINS.values) }
scope :confirmed, -> { where(accepted_coc: true, synced: true).where.not(aoc_id: nil) }
Expand All @@ -37,13 +39,24 @@ class User < ApplicationRecord
after_create :assign_private_leaderboard

def self.from_kitt(auth)
user = where(provider: auth.provider, uid: auth.uid).first_or_create do |u|
batches = auth.info&.schoolings
oldest_batch = batches.min_by { |batch| batch.camp.starts_at }

user = find_or_initialize_by(provider: auth.provider, uid: auth.uid) do |u|
u.username = auth.info.github_nickname
u.github_username = auth.info.github_nickname
u.batch_id = Batch.find_or_create_by(number: auth.info.last_batch_slug.to_i).id

u.batch = Batch.find_or_initialize_by(number: oldest_batch&.camp&.slug) do |b|
city = oldest_batch&.city
b.city = City.find_or_initialize_by(name: city&.slug, vanity_name: city&.name)
end
Aquaj marked this conversation as resolved.
Show resolved Hide resolved

u.city = u.batch.city
end

user.update(github_username: auth.info.github_nickname)
user.github_username = auth.info.github_nickname

user.save

user
end

Expand Down Expand Up @@ -101,6 +114,18 @@ def not_referring_self
errors.add(:referrer, "must not be you") if referrer == self
end

def not_changing_cities
return if city_id_was.blank?

errors.add(:city_id, "can't be modified") if city_id_changed?
end

def city_must_match_batch
return unless batch&.city_id?

errors.add(:city_id, "must match batch city") if city_id != batch.city_id
end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Qu'ets ce qui se passe si tu as une city mais pas de batch ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Le return unless batch&.city_id? ligne 124 fera que la validation sera juste pas appliquée.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sauf que tu as changé le model du Batch en disant que la city est optional.
Ca veut dire que tu pourrais avoir un batch avec un city_id nil qui casserait ensuite la validation non ?

Copy link
Collaborator Author

@Aquaj Aquaj Nov 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pour ça que le return checke aussi la présence de la city sur le Batch. Si le batch n'a pas de city_id on skippe aussi la validation.

C'est obsolète par contre si on permet pas de choisir son batch. L'optional sur Batch#city saute et on redeviendra juste return unless batch.present? ici pour la simplicité.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah oui j'avais zappé le &


def assign_private_leaderboard
return if private_leaderboard.present?

Expand Down
10 changes: 10 additions & 0 deletions db/migrate/20231116030303_add_back_city_on_users.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true

class AddBackCityOnUsers < ActiveRecord::Migration[7.1]
disable_ddl_transaction!

def change
add_reference :users, :city, index: { algorithm: :concurrently }
add_foreign_key :users, :cities, validate: false
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class AddForeignKeyForUsersCityRelationship < ActiveRecord::Migration[7.1]
def change
validate_foreign_key :users, :cities
end
end
5 changes: 4 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.1].define(version: 2023_11_01_144409) do
ActiveRecord::Schema[7.1].define(version: 2023_11_16_030521) do
# These are extensions that must be enabled in order to support this database
enable_extension "citext"
enable_extension "pgcrypto"
Expand Down Expand Up @@ -374,6 +374,7 @@
t.boolean "accepted_coc", default: false, null: false
t.integer "aoc_id"
t.bigint "batch_id"
t.bigint "city_id"
t.datetime "created_at", null: false
t.boolean "entered_hardcore", default: false, null: false
t.string "github_username"
Expand All @@ -389,6 +390,7 @@
t.string "username"
t.index ["aoc_id"], name: "index_users_on_aoc_id", unique: true
t.index ["batch_id"], name: "index_users_on_batch_id"
t.index ["city_id"], name: "index_users_on_city_id"
t.index ["referrer_id"], name: "index_users_on_referrer_id"
end

Expand All @@ -406,5 +408,6 @@
add_foreign_key "squad_points", "squads"
add_foreign_key "squad_scores", "squads"
add_foreign_key "users", "batches"
add_foreign_key "users", "cities"
add_foreign_key "users", "users", column: "referrer_id"
end
1 change: 1 addition & 0 deletions spec/factories/users.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
username { "pil0u" }
synced { true }
uid { id }
city_id { batch&.city_id }
wJoenn marked this conversation as resolved.
Show resolved Hide resolved
end
end