2010-05-13 13 views
4

Je ne fais que plonger dans Datamapper (et Sinatra) et j'ai une question sur les associations. Voici quelques modèles que j'ai. C'est ce que je veux mettre en œuvre. J'ai un problème avec Workoutitems et Workout. Workout sera géré séparément, mais Workoutitems a un seul entraînement associé à chaque ligne.Commençant par Datamapper, question de l'association

  1. séance d'entraînement - juste une liste des types de séances d'entraînement (course, levage, redressements assis, etc.)
  2. séance d'entraînement sélectionné - ce est le nom d'un ensemble de séances d'entraînement, ainsi que des notes par l'utilisateur et entraîneur. Il a une collection de N workoutitems
  3. Workoutitems - cela prend un entraînement et un certain nombre de répétitions qui vont dans le jeu d'entraînement.

     
    class Workout 
        include DataMapper::Resource 
        property :id,  Serial #PK id 
        property :name, String, :length=>50,:required=>true # workout name 
        property :description, String, :length=>255 #workout description 
    end 
    
    
    class Selectedworkout 
        include DataMapper::Resource 
        property :id, Serial 
        property :name, String, :length=>50, :required=>true 
        property :workout_time, String, :length=>20 
        property :user_notes, String, :length=>255 
        property :coach_notes, String, :length=>255 
        has n, :workoutitems 
    end 
    
    class Workoutitem 
        include DataMapper::Resource 
        property :id, Serial 
        property :reps, String, :length=>50, :required=>true 
        belongs_to :selectedworkout 
    end 
    

Répondre

4

Avant de répondre, je vais souligner que la convention rubis typique (ce qui est pertinent pour DataMapper vous verrez dans une seconde) est d'avoir des noms de classe comme SelectedWorkout et WorkoutItem , plutôt que Selectedworkout et Workoutitems. DataMapper nomme automatiquement vos relations à partir des noms de classe, il est donc utile de suivre la convention. Excuses si c'est confus, mais dans le but de la réponse, je vais supposer que vous pouvez renommer vos modèles:

Étant donné que votre modèle d'entraînement est essentiellement une collection normalisée de données de WorkoutItem, je suggère que WorkoutItem.belongs_to(:workout) (et accessoirement c'est une commande que vous pourriez lancer depuis IRB, et ça marcherait très bien, ou vous pouvez coller le belongs_to :workout dans la classe du modèle bien sûr).

Il semble que SelectedWorkout soit votre interface principale dans vos données, donc je présume que vous allez faire des choses comme dire @user.selected_workouts.first.workout_items (pour les éléments de la première séance d'entraînement sélectionnée) ou similaire.

Soit dit en passant, vous pouvez aller plus loin et utiliser WorkoutItem comme une jointure modèle entre la séance d'entraînement et SelectedWorkout, si les relations suivantes sont mises en place:

WorkoutItem.belongs_to(:workout)

WorkoutItem.belongs_to(:selected_workout)

SelectedWorkout.has(Infinity, :workout_items) # n == Infinity inside a Model

Une fois la relation précédente établie, vous pouvez dire:

SelectedWorkout.has(Infinity, :workouts, :through => :workout_items)

De même, vous mettre en place l'autre côté de la relation a beaucoup à travers la même façon:

Workout.has(Infinity, :workout_items)

Workout.has(Infinity, :selected_workouts, :through => :workout_items

Maintenant, vous pouvez faire des choses cool comme @selected_workout.workouts.map{ |w| w.name }. Ou si vous voulez trouver tous les entraînements sélectionnés qui incluent un entraînement particulier, vous pouvez dire @workout.selected_workouts.

Ou vous pouvez faire des choses plus intéressantes à travers la syntaxe de requête de DataMapper comme ceci:

@workouts_that_dont_require_gear = SelectedWorkouts.all("workouts.name" => ["Situps", "Pullups", "Pushups"])