#14 Performing Calculations on Models
ActiveRecord fournit plusieurs façons différentes pour effectuer des manipulations sur les modèles. Pour démontrer ça, nous allons utiliser un modèle Task
qui a un champ de type entier appelé priority
et regarder quelques une de ses méthodes via script/console
. Pour chaque méthode, le SQL généré par Rails est montré à la suite.
On peut trouver la priorité de la première tâche comme ceci :
>> Task.first.priority
=> 3
SELECT * FROM "tasks" LIMIT 1
Comment faire si nous voulons la somme des priorités de toutes les tâches ?
>> Task.sum(:priority)
=> 12
SELECT sum("tasks".priority) AS sum_priority FROM "tasks"
Nous pouvons même passer des conditions :
>> Task.sum(:priority, :conditions => {:completed => false })
=> 2
SELECT sum("tasks".priority) AS sum_priority FROM "tasks" WHERE (completed="f")
Aussi bien que sum
il existe d'autres méthodes, comme minimum
, maximum
et average
:
>> Task.minimum(:priority)
=> 2
SELECT min("tasks".priority) AS min_priority FROM "tasks"
>> Task.maximum(:priority)
=> 5
SELECT max("tasks".priority) AS max_priority FROM "tasks"
>> Task.average(:priority).to_f
=> 3.0
SELECT avg("tasks".priority) AS avg_priority FROM "tasks"
Le SQL généré par Rails quand ces méthodes sont utilisées les rends plus efficaces que de calculer ces valeurs en utilisant Ruby pour retourner toutes les Tasks
et calculer les valeurs.
Utiliser les méthodes avec des associations.
Ces méthodes sont des méthodes de classe donc elles peuvent être utiliser via des associations. Si nous avons un modèle Project
, lequel a beaucoup de tâches (has_many :tasks
), nous pouvons accéder à ces méthodes pour les tâches d'un projet spécifique. Noter que, comme avant, nous pouvons passer des conditions à la méthode find
.
>> project = Project.first
=> #<Project id: 1, title: "A Project">
>> project.tasks.sum(:priority, :conditions => {:completed => true})
=> 10
Ceci exécute le SQL suivant :
SELECT sum("tasks".priority) AS sum_priority FROM "tasks" WHERE ("tasks"."completed" = 't') AND ("tasks".project_id = 1)