我有一个有很多课程的学生。在学生#upcate动作和表单中,我接受course_ids列表。当该列表发生变化时,我想调用某个函数。如果update_attributes创建了course_student,则会调用我的代码,但如果update_attributes销毁了course_student,则不会被调用。我可以解决这个问题,还是我必须自己检测这些更改?
# app/models/student.rb
class Student < ActiveRecord::Base
belongs_to :teacher
has_many :grades
has_many :course_students, :dependent => :destroy
has_many :courses, :through => :course_students
has_many :course_efforts, :through => :course_efforts
# Uncommenting this line has no effect:
#accepts_nested_attributes_for :course_students, :allow_destroy => true
#attr_accessible :first_name, :last_name, :email, :course_students_attributes
validates_presence_of :first_name, :last_name
...
end
# app/models/course_student.rb
class CourseStudent < ActiveRecord::Base
after_create :reseed_queues
before_destroy :reseed_queues
belongs_to :course
belongs_to :student
private
def reseed_queues
logger.debug "******** attempting to reseed queues"
self.course.course_efforts.each do |ce|
ce.reseed
end
end
end
# app/controllers/students_controller.rb
def update
params[:student][:course_ids] ||= []
respond_to do |format|
if @student.update_attributes(params[:student])
format.html { redirect_to(@student, :notice => 'Student was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @student.errors, :status => :unprocessable_entity }
end
end
end
答案 0 :(得分:7)
事实证明,此行为已记录在 has_many 方法上。从API文档:
<强>集合=对象强> 通过适当删除和添加对象来替换集合内容。如果:through选项为true,则连接模型中的回调将被触发,但destroy回调除外,因为删除是直接的。
我不确定“因为删除是直接的”意味着什么,但我们有它。
答案 1 :(得分:1)
接受嵌套属性需要一个标志来触发嵌套销毁。至少它确实回来了。
答案 2 :(得分:1)
如果你添加dependent: :destroy
,它就会尊重这一点。请注意,如果您使用has_many
through:
,则需要将该选项添加到两者。
has_many :direct_associations, dependent: :destroy, autosave: true
has_many :indirect_associations, through: :direct_associations, dependent: :destroy
(我在Rails 3中使用过它,我敢打赌它也适用于Rails 4)
答案 3 :(得分:1)
使用update / update_attributes删除记录时,会触发delete
方法,而不是destroy
。
@student.update_attributes(params[:student])
Delete
方法skips回调,因此不会调用after_create
/ before_destroy
。
可以使用删除记录并支持回调的accepts_nested_attributes_for代替。{/ p>
accepts_nested_attributes_for :courses, allow_destroy: true
@student.update_attributes(courses_attributes: [ {id: student_course_association_id, _destroy: 1 } ])
答案 4 :(得分:0)
如果您的CourseStudent
指定belongs_to :student, :dependent => :destroy
,那么没有学生,似乎CourseStudent记录无效。
尝试按照上面链接的LH讨论进行操作,并this one我还尝试在before_destroy
下面的CourseStudent中移动belongs_to
回调。链接的示例演示了回调的顺序如何与after_create
重要,可能同样适用于before_destroy
。当然,既然你正在使用Edge Rails,我也会尝试RC,也许他们修复了一个错误。
如果没有这些东西,我会尝试制作一个非常简单的Rails应用程序,其中有两个模型可以演示问题并将其发布到Rails的灯塔。
答案 5 :(得分:0)
无法发表评论,所以我只想添加一个答案条目。
刚遇到同样的错误。经过几个小时的尝试来解决这个问题和一个小时的谷歌,我偶然发现了这个问题。除了链接的LH票证,以及来自API的引用,它现在也是有意义的。谢谢!
谷歌搜索时发现了一张旧票。直接链接不起作用,但谷歌缓存有副本。 只需查看Google的dev.rubyonrails.org/ticket/7743缓存版即可似乎补丁从未进入Rails。