Skip to content

Commit

Permalink
Fix student search (#1331)
Browse files Browse the repository at this point in the history
- [x] use distinct instead of uniq
- [x] use regex
- [x] simplify query
  • Loading branch information
pskl authored Jan 15, 2025
1 parent 14a5777 commit edcbae0
Show file tree
Hide file tree
Showing 7 changed files with 47 additions and 29 deletions.
26 changes: 4 additions & 22 deletions app/controllers/students_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

class StudentsController < ApplicationController
before_action :set_student, :check_student!, only: :show
before_action :sanitize_search, :set_search_result, only: :search_results

rescue_from ActiveRecord::RecordNotFound, with: :redirect_to_class

before_action :set_search_result, only: :search_results

def show
@schoolings = @student.schoolings

Expand All @@ -30,28 +31,9 @@ def redirect_to_class
redirect_to school_year_classes_path(selected_school_year), alert: t("errors.students.not_found")
end

# rubocop:disable Layout/LineLength
def set_search_result
search_str = "%#{@name}%"
@students = current_establishment.students.where(
"
TRANSLATE(TRANSLATE(UNACCENT(last_name), $$',$$, ''), '-', ' ') ILIKE TRANSLATE(TRANSLATE(UNACCENT(:search_str), $$',$$, ''), '-', ' ') OR
TRANSLATE(TRANSLATE(UNACCENT(first_name), $$',$$, ''), '-', ' ') ILIKE TRANSLATE(TRANSLATE(UNACCENT(:search_str), $$',$$, ''), '-', ' ') OR
TRANSLATE(TRANSLATE(UNACCENT(CONCAT(last_name, ' ', first_name)), $$',$$, ''), '-', ' ') ILIKE TRANSLATE(TRANSLATE(UNACCENT(:search_str), $$',$$, ''), '-', ' ') OR
TRANSLATE(TRANSLATE(UNACCENT(CONCAT(first_name, ' ', last_name)), $$',$$, ''), '-', ' ') ILIKE TRANSLATE(TRANSLATE(UNACCENT(:search_str), $$',$$, ''), '-', ' ')
", search_str:
).uniq
# Dans l'idéal, utiliser la REGEX '%' :
# TRANSLATE(UNACCENT(last_name), $$-', $$, $$%$$) ILIKE TRANSLATE(UNACCENT(:search_str), $$-', $$, $$%$$) OR
# TRANSLATE(UNACCENT(first_name), $$-', $$, $$%$$) ILIKE TRANSLATE(UNACCENT(:search_str), $$-', $$, $$%$$) OR
# TRANSLATE(UNACCENT(CONCAT(last_name, '%', first_name)), $$-', $$, $$%$$) ILIKE TRANSLATE(UNACCENT(:search_str), $$-', $$, $$%$$) OR
# TRANSLATE(UNACCENT(CONCAT(first_name, '%', last_name)), $$-', $$, $$%$$) ILIKE TRANSLATE(UNACCENT(:search_str), $$-', $$, $$%$$)
end
# rubocop:enable Layout/LineLength

def sanitize_search
return if params[:name].blank?

@name = params[:name]

@students = current_establishment.find_students(@name)
end
end
20 changes: 20 additions & 0 deletions app/models/establishment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,26 @@ def invites?(email)
invitations.exists?(email: email)
end

def find_students(name)
search_terms = name
.strip
.gsub(/[^[:alnum:]\s]/, "")
.split
.map { |term| "%#{Student.sanitize_sql_like(term)}%" }

students
.includes(current_schooling: :classe)
.where(
search_terms.map do
"(regexp_replace(unaccent(first_name), '[^[:alnum:]]', '', 'g') ILIKE ? OR " \
"regexp_replace(unaccent(last_name), '[^[:alnum:]]', '', 'g') ILIKE ?)"
end.join(" OR "),
*search_terms.flat_map { |term| [term, term] }
)
.unscope(:order)
.distinct
end

def select_label
[uai, name].compact.join(" - ")
end
Expand Down
1 change: 0 additions & 1 deletion app/views/students/search_results.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
%tr
%td= dsfr_link_to student.full_name, student_path(student)
%td
// TODO: Risque de N+1 ?
-if student.current_schooling.nil?
Aucune scolarité active
-else
Expand Down
2 changes: 1 addition & 1 deletion config/initializers/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# frozen_string_literal: true

module Aplypro
VERSION = "2.0.11"
VERSION = "2.1.0"
end
4 changes: 2 additions & 2 deletions db/schema.rb

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

7 changes: 4 additions & 3 deletions features/recherche.feature
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
# language: fr
Fonctionnalité: Recherche
Fonctionnalité: Recherche d'étudiants par nom et prénom
Contexte:
Sachant que je suis un personnel MENJ directeur de l'établissement "DINUM"
Et que l'API SYGNE renvoie 10 élèves dans une classe "1MELEC" dont "Jüãn-Frânçois Mîchäèl-d'Estaing" pour l'établissement "DINUM"
Et que je me connecte en tant que personnel MENJ
Et que je passe l'écran d'accueil
Et que toutes les tâches de fond sont terminées

Scénario: Le personnel veut rechercher un élève
Scénario: Le personnel veut rechercher un élève en utilisant nom et/ou prénom
Quand je recherche l'élève "a"
Alors la page contient "Recherche d'un élève"
Et la page contient "résultats trouvés pour la recherche : a"
Quand je recherche l'élève "XRTEZEDE"
Alors la page contient "Aucun résultat trouvé pour la recherche : XRTEZEDE"
Quand je recherche l'élève "juan francois michael dest"
Alors la page contient "Jüãn-Frânçois Mîchäèl-d'Estaing"

Quand je recherche l'élève "juan-francois"
Alors la page contient "Jüãn-Frânçois Mîchäèl-d'Estaing"
16 changes: 16 additions & 0 deletions spec/models/establishment_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,20 @@
end
end
end

describe "#find_students" do
let(:etab) { create(:classe, :with_students, students_count: 5).establishment }

before do
etab.students.first.update!(first_name: "Tibal", last_name: "N'Guy-ôme")
end

it "strips apostrophes" do
expect(etab.find_students("nguyom")).to contain_exactly(Student.find_by!(last_name: "N'Guy-ôme"))
end

it "finds students with partial names" do
expect(etab.find_students("ibal")).to contain_exactly(Student.find_by!(first_name: "Tibal"))
end
end
end

0 comments on commit edcbae0

Please sign in to comment.