Les scopes en Rails reprĂ©sente la passerelle entre le langage mĂ©tier et une requĂȘte SQL.
Lâobjectif est que chacun(e) sache comment Ă©crire un bon scope et le tester
<aside> â PrĂ©-requis
<aside> â Temps indicatif : 30min
</aside>
Le nom du scope doit utiliser le langage du Product Owner
Un scope peut prendre un ou plusieurs arguments
La requĂȘte SQL doit rester dans le cadre stricte du scope
Pas includes, order ou autres
superflus
Raison :
En utilisant le vocabulaire métier, il suffit de reprendre les mots du product owner en appelant les scopes pour réaliser sa demande.
Extraire une partie de la requĂȘte SQL permet aussi de simplifier lâĂ©criture de test
scope :pour_le_jour, ->(*jours) { where('EXTRACT(ISODOW FROM date) IN (?)', jours.flatten) }
scope :uniquement_le_lundi, -> { pour_le_jour(1) }
scope :sans_photo_detouree, -> { where.missing(:photo_detouree_attachment) }
# Ici on place la compléxité dans ce scope
# Le nom reprend les termes exactes données par le Product Owner
scope :pour_meteo_du_jour,
lambda { |utilisateur|
meteo = Meteo.du_jour.pour_utilisateur(utilisateur).first
if meteo
where('temperature_maximale >= ?', meteo.temperature_max)
.where('temperature_minimale <= ?', meteo.temperature_min)
.where('ARRAY[?] && conditions_meteo::text[]', meteo.temps)
end
}
spec/models/
context
par casdescribe
:
describe '.nom_du_scope' do
Raison :
Il sâagit de test dâintĂ©gration (et non unitaire !) car ces tests utilisent la base de donnĂ©e.
Le .
avant le nom_du_scope dans le describe
indique que lâon test une mĂ©thode de class
describe '.pour_meteo_du_jour' do
# on évite de trop créer d'objet en amont pour la maintenabilité
# on extrait la logique des context dans les [traits](<https://thoughtbot.com/blog/remove-duplication-with-factorybots-traits>)
let(:utilisateur) { create(:utilisateur) }
let!(:template_tenue) { create(:template_tenue, :ensoleille) }
let(:resultat) { described_class.pour_meteo_du_jour(utilisateur) }
# cas positif đ
context "quand l'utilisateur a une météo du jour" do
before(:each) { create :meteo, :ensoleille, utilisateur: utilisateur }
it 'retourne le template' do
expect(resultat).to include template_tenue
end
end
# cas nĂ©gatif đ
context "quand l'utilisateur a une météo du jour mais avec une mauvaise temperature" do
before(:each) { create :meteo, :glacial, utilisateur: utilisateur }
it 'ne retourne pas le template' do
expect(resultat).not_to include template_tenue
end
end
# autre cas
context "quand l'utilisateur n'a pas de météo" do
it 'retourne tous les templates tenues' do
expect(resultat.size).to eq TemplateTenue.all.count
end
end
end
Tester uniquement le cas positif
Le describe du scope dans le test doit ĂȘtre .ma_methode
et non #ma_methode