我只是潜入Datamapper(和Sinatra)并对关联有疑问。以下是我的一些型号。这就是我想要实现的。我在Workoutitems和Workout方面遇到了问题。锻炼将单独管理,但Workoutitems只有一个与每行相关的锻炼。
锻炼项目 - 这需要锻炼并在训练集中进行多次重复。
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
答案 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"])