Skip to content

Commit

Permalink
🛠️ Zones | Add LAST_ZONE and Remove N+1 for zones queries
Browse files Browse the repository at this point in the history
  • Loading branch information
ThibautPoullain committed Nov 5, 2024
1 parent d61078d commit 19fb7de
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 35 deletions.
3 changes: 3 additions & 0 deletions app/controllers/administrateurs/procedures_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ def edit
end

def zones
@zones = Zone.available_at(@procedure.published_or_created_at, current_administrateur.default_zones)
.partition { |zone| zone.label == Zone::LAST_ZONE }
.then { |last_zone, other_zones| other_zones + last_zone }
end

def create
Expand Down
17 changes: 13 additions & 4 deletions app/models/zone.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,31 @@ class Zone < ApplicationRecord
has_many :labels, -> { order(designated_on: :desc) }, class_name: 'ZoneLabel', inverse_of: :zone
has_and_belongs_to_many :procedures, -> { order(published_at: :desc) }, inverse_of: :zone

LAST_ZONE = 'Autre'.freeze

def current_label
labels.where.not(name: 'Non attribué').first.name
end

def label_at(date)
label = labels.where('designated_on < ?', date)&.first || labels.last
label.name
labels.where('designated_on < ?', date).first&.name || labels.last&.name
end

def available_at?(date)
label_at(date) != 'Non attribué'
end

def self.available_at(date, without_zones = [])
(Zone.all - without_zones).filter { |zone| zone.available_at?(date) }.sort_by { |zone| zone.label_at(date) }
.map do |zone|
zones = Zone.includes(:labels).where.not(id: without_zones).to_a

zone_labels = zones.each_with_object({}) do |zone, labels|
label = zone.labels.filter { |l| l.designated_on < date }.max_by(&:designated_on)
labels[zone.id] = label&.name || ''
end

available_zones = zones.filter { |zone| zone_labels[zone.id] != 'Non attribué' }

available_zones.map do |zone|
LabelModel.new(id: zone.id, label: zone.label_at(date))
end
end
Expand Down
2 changes: 1 addition & 1 deletion app/views/administrateurs/procedures/zones.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
.fr-checkbox-group
= b.check_box
= b.label class: "fr-label font-weight-bold"
= f.collection_check_boxes :zone_ids, Zone.available_at(@procedure.published_or_created_at, current_administrateur.default_zones), :id, :label do |b|
= f.collection_check_boxes :zone_ids, @zones, :id, :label do |b|
.fr-fieldset__element
.fr-checkbox-group
= b.check_box
Expand Down
32 changes: 31 additions & 1 deletion spec/controllers/administrateurs/procedures_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -484,8 +484,38 @@
let(:procedure) { create(:procedure, administrateur: admin) }
let(:procedure_id) { procedure.id }

let(:last_zone) { create(:zone, labels: [{ designated_on: '1981-05-08', name: 'Autre' }]) }
let(:other_zone_1) { create(:zone, labels: [{ designated_on: '1981-05-08', name: 'Zone 1' }]) }
let(:other_zone_2) { create(:zone, labels: [{ designated_on: '1981-05-08', name: 'Zone 2' }]) }

before do
procedure.zones << [last_zone, other_zone_1, other_zone_2]
end

subject { get :zones, params: { id: procedure_id } }
it { is_expected.to have_http_status(:success) }

it 'returns a successful response' do
subject
expect(response).to have_http_status(:success)
end

it 'assigns @zones with the correct order' do
subject
assigned_labels = assigns(:zones).map(&:label)
expect(assigned_labels).to eq(['Zone 1', 'Zone 2', 'Autre'])
end

it 'assigns @zones including all expected zones' do
subject
assigned_labels = assigns(:zones).map(&:label)
expect(assigned_labels).to include('Zone 1', 'Zone 2', 'Autre')
end

it 'places the LAST_ZONE at the end' do
subject
assigned_zones = assigns(:zones)
expect(assigned_zones.last.label).to eq('Autre')
end
end

describe 'POST #create' do
Expand Down
63 changes: 34 additions & 29 deletions spec/views/administrateurs/procedures/zones.html.haml_spec.rb
Original file line number Diff line number Diff line change
@@ -1,52 +1,57 @@
# frozen_string_literal: true

describe 'administrateurs/procedures/zones' do
let(:administrateur) { administrateurs(:default_admin) }
let(:procedure) { create(:procedure) }
let(:populate_zones_task) { Rake::Task['after_party:populate_zones_with_tchap_hs'] }
require 'rails_helper'

RSpec.describe 'administrateurs/procedures/zones', type: :view do
let(:administrateur) { create(:administrateur) }
let(:procedure) { create(:procedure, published_at: Time.zone.parse('2022-07-20')) } # Définir une date de publication de la procédure plus tardive
let!(:zone1) { create(:zone, acronym: 'MTEI', labels: [{ designated_on: '2022-05-18', name: "Ministère du Travail" }]) }
let!(:zone2) { create(:zone, acronym: 'MEP', labels: [{ designated_on: '2022-05-18', name: "Ministère des vacances" }]) }

before do
Rails.application.config.ds_zonage_enabled = true
populate_zones_task.invoke
allow(view).to receive(:current_administrateur).and_return(administrateur)
assign(:procedure, procedure)
assign(:zones, Zone.available_at(procedure.published_or_created_at, administrateur.default_zones))
end

after do
populate_zones_task.reenable
it 'affiche le titre de la page' do
render
expect(rendered).to include('Zones')
end

context 'when procedure has never been published' do
before { Timecop.freeze(now) }
after { Timecop.return }
it 'affiche les zones par défaut de l’administrateur' do
allow(administrateur).to receive(:default_zones).and_return([zone1])
assign(:zones, Zone.available_at(procedure.published_or_created_at, administrateur.default_zones))
render

let(:procedure) { create(:procedure, zones: [Zone.find_by(acronym: 'MTEI')]) }
let(:now) { Time.zone.parse('18/05/2022') }
expect(rendered).to match(/Ministère du Travail/)
end

it 'displays zones with label available at the creation date' do
assign(:procedure, procedure)
render
it 'affiche toutes les zones disponibles' do
render

expect(rendered).to have_content("Ministère du Travail")
expect(rendered).not_to have_content("Ministère du Travail, du Plein emploi et de l'Insertion")
end
expect(rendered).to match(/Ministère du Travail/)
expect(rendered).to match(/Ministère des vacances/)
end

context 'when procedure has been published' do
before { Timecop.freeze(now) }
after { Timecop.return }
it 'affiche les actions en bas de page' do
render

let(:procedure) { create(:procedure, zones: [Zone.find_by(acronym: 'MTEI')]) }
let(:now) { Time.zone.parse('18/05/2022') }
expect(rendered).to include('Annuler')
expect(rendered).to include('Enregistrer')
end

it 'displays zones with label available at the creation date' do
Timecop.freeze(Time.zone.parse('22/05/2022')) do
procedure.publish!
end
context 'quand le zonage est désactivé' do
before do
Rails.application.config.ds_zonage_enabled = false
end

assign(:procedure, procedure)
it 'n’affiche pas les zones' do
render

expect(rendered).to have_content("Ministère du Travail, du Plein emploi et de l'Insertion")
expect(rendered).not_to match(/Ministère du Travail/)
expect(rendered).not_to match(/Ministère des vacances/)
end
end
end

0 comments on commit 19fb7de

Please sign in to comment.