从Datamapper开始,关联问题

时间:2010-05-13 11:45:01

标签: ruby associations datamapper

我只是潜入Datamapper(和Sinatra)并对关联有疑问。以下是我的一些型号。这就是我想要实现的。我在Workoutitems和Workout方面遇到了问题。锻炼将单独管理,但Workoutitems只有一个与每行相关的锻炼。

  1. 锻炼 - 只是一个类型的列表 锻炼(跑步,举起,仰卧起坐等)
  2. 选择锻炼 - 这个 是一组训练的名称, 以及用户的笔记和 教练。它有一个N的集合 workoutitems
  3. 锻炼项目 - 这需要锻炼并在训练集中进行多次重复。

    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
    

1 个答案:

答案 0 :(得分:4)

在我回答之前,我将指出典型的ruby约定(与您在一秒钟内看到的DataMapper相关)是具有类名称如SelectedWorkout和WorkoutItem,而不是Selectedworkout和Workoutitems。 DataMapper从类名自动命名您的关系,因此遵循约定很有用。抱歉,如果它令人困惑,但为了答案的目的,我将假设你可以重命名你的模型:

鉴于您的Workout模型本质上是来自WorkoutItem的标准化数据集合,我建议WorkoutItem.belongs_to(:workout)(顺便说一下,这是一个可以从IRB运行的命令,它可以正常工作,或者你当然可以将belongs_to :workout粘贴在模型类中。

似乎SelectedWorkout是您数据的主要界面,因此我假设您将执行诸如@user.selected_workouts.first.workout_items(对于第一个选定的锻炼项目)等的事情。

顺便提一下,如果设置了以下关系,您可以更进一步,使用WorkoutItem作为Workout和SelectedWorkout之间的连接模型:

WorkoutItem.belongs_to(:workout)

WorkoutItem.belongs_to(:selected_workout)

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

设置上一个关系后,您可以说:

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

同样,你设置了很多通过关系的另一面:

Workout.has(Infinity, :workout_items)

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

现在,你可以做一些很酷的事情,比如@selected_workout.workouts.map{ |w| w.name }。或者,如果您想查找包含特定锻炼的所有选定锻炼,您可以说@workout.selected_workouts

或者你可以通过DataMapper的查询语法做更多令人兴奋的事情:

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