我有以下资源关系:
Class Course < ActiveRecord::Base
has_many :track_courses
has_many :tracks, through: :track_courses
end
以及Track模型中的镜像关系。连接这些模型的TrackCourse表包含以下行:
id:主键
track_id:代表曲目
course_id:代表课程
位置:该曲目内的课程顺序
我希望管理员用户能够通过ajax更新每首曲目中的课程。我在前端有一个列表,它作为哈希传递给控制器:
front_end_list = { course_id => position }
表示对象及其在前端可排序的位置。
我也在查找该曲目中现有课程的列表:
existing_courses = TrackCourse.where("track_id = ?", track_id).all
目标:比较这两个列表并根据前端列表同步数据库条目。基本上,如果用户将课程15插入到网页上的位置2,我需要将该条目插入TrackCourse表(如果它不存在)或更新其位置(如果存在)。反之亦然。
这样做的最佳方式是什么? ActiveRecord / ActiveRelation是否提供了相应的方法?或者我必须自己写点什么?
更新:我找到了一个名为acts_as_list的gem,但它似乎是为ActiveRecord表设计的而不是ActiveRelation。它基本上期望位置值是唯一的,而在TrackCourse中可以有多个具有相同位置的路线(在不同的轨道中)。
答案 0 :(得分:0)
我找到了解决方案。我会在这里发布我的代码,以防它帮助其他任何人。
我的控制器中有这个方法来处理来自前端的ajax请求:
def sort
track_id = params[:track_id]
courses_in_list = {}
params[:course].each do |courseid|
position = params[:course].index(courseid)
courses_in_list[courseid.to_i] = position
end
existing_courses_in_track = {}
TrackCourse.where("track_id = ?", track_id).to_a.each do |track_course|
existing_courses_in_track[track_course.course_id] = track_course.position
end
if courses_in_list.length < existing_courses_in_track.length
existing_courses_in_track.each do |courseid, position|
if courses_in_list[courseid].nil?
track_course = TrackCourse.where(track_id: track_id, course_id: courseid).first
track_course.remove_from_list
track_course.destroy!
end
end
else
if existing_courses_in_track.empty?
track_course = TrackCourse.new(track_id: track_id,
course_id: courses_in_list.keys[0])
track_course.insert_at(courses_in_list.values[0])
p "first track!"
else
courses_in_list.each do |courseid, position|
track_exists = false
if !existing_courses_in_track[courseid].nil?
track_course_position = existing_courses_in_track[courseid]
track_exists = true
end
if !track_exists
TrackCourse.new(track_id: track_id, course_id: courseid).insert_at(position)
else
p "else statement"
track_course = TrackCourse.where(track_id: track_id, course_id: courseid).first
track_course.update_attribute(:position, position)
end
end
end
end
render :nothing => true
end
基本上,我正在构建两个哈希值,一个基于前端项目列表及其位置,一个基于数据库课程及其位置。然后我比较它们。如果前端列表较短,则表示用户删除了一个项目,因此我遍历后端列表,找到额外的项目,然后将其删除。然后我使用类似的机制将项目添加到列表并使用列表。 acts_as_list宝石真的有助于保持正确的位置。但是,当我将其包含在我的模型中时,我确实必须限制其范围,以确保它仅在具有特定track_id的关系(TrackCourses)上运行。