Ruby on rails 之前,销毁不是从更新属性触发

Ruby on rails 之前,销毁不是从更新属性触发,ruby-on-rails,collections,associations,callback,Ruby On Rails,Collections,Associations,Callback,我有一个学生有很多课程。在学生更新操作和表单中,我接受课程ID列表。当列表改变时,我想调用某个函数。如果update_属性创建了一个course_学生,则会调用我的代码,但是如果update_属性销毁了一个course_学生,则不会调用我的代码。我可以让它启动吗,还是我必须自己检测变化 # app/models/student.rb class Student < ActiveRecord::Base belongs_to :teacher has_many :grades h

我有一个学生有很多课程。在学生更新操作和表单中,我接受课程ID列表。当列表改变时,我想调用某个函数。如果update_属性创建了一个course_学生,则会调用我的代码,但是如果update_属性销毁了一个course_学生,则不会调用我的代码。我可以让它启动吗,还是我必须自己检测变化

# 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
#app/models/student.rb
班级学生:毁灭
有很多:课程,:至=>:课程\u学生
有很多:当然努力,:通过=>:当然努力
#取消对此行的注释无效:
#为:课程学生接受\u嵌套的\u属性,:允许\u销毁=>true
#属性可访问:名字、姓氏、电子邮件、课程、学生属性
验证是否存在:first\u name、:last\u name
...
结束
#app/models/course_student.rb
类CourseStudent“student已成功更新”)}
format.xml{head:ok}
其他的
format.html{render:action=>“edit”}
format.xml{render:xml=>@student.errors,:status=>:unprocessable_entity}
结束
结束
结束

如果您的
课程学生
指定
属于\u:student,:dependent=>:destroy
,那么如果没有学生,课程学生记录似乎是无效的

尝试跟随我上面链接的LH讨论,我还尝试在课程中删除
回调之前将
移到
所属的
下方。链接的示例演示了回调顺序如何影响创建后的
,销毁前的
。当然,由于您使用的是Edge Rails,我也会尝试使用RC,也许他们修复了一个bug


如果做不到这些,我会尝试用两个模型制作一个非常简单的Rails应用程序,演示问题并将其发布到Rails的Lighthouse。

接受嵌套属性需要一个标志来触发嵌套销毁。至少它是在。

无法留下评论时做的,所以我只添加一个答案条目

只是遇到了同样的错误。在花了几个小时试图解决这个问题,用谷歌搜索了一个小时之后,我偶然发现了这个问题。与链接的LH票证和API中的引用一起,它现在是有意义的。谢谢大家!

在谷歌搜索时,我发现了一张旧票。直接链接不起作用,但谷歌缓存有一个副本。 只需在谷歌上查看dev.rubyonrails.org/ticket/7743的缓存版本


似乎有一个补丁从来没有出现在Rails上。

事实证明,这种行为是有文档记录的,就在的许多方法中。从API文档中:

集合=对象 根据需要,通过删除和添加对象替换集合内容。如果:through选项为true,则会触发联接模型中的回调(销毁回调除外),因为删除是直接的


我不确定“因为删除是直接的”是什么意思,但我们有它。

如果您添加
dependent::destroy
,它将尊重这一点。请注意,如果您使用的
有许多通过:
,则需要将该选项添加到这两个选项中

  has_many :direct_associations, dependent: :destroy, autosave: true
  has_many :indirect_associations, through: :direct_associations, dependent: :destroy

(我在Rails 3中使用过,我打赌它也会在Rails 4上工作)

当使用update/update\u属性删除记录时,它会触发
delete
方法,而不是
destroy

@student.update_属性(参数[:student])

Delete
方法回调,因此不会调用创建之后的
/\u销毁之前的
。
可以使用删除记录并支持回调的替代方法

接受:课程的\u嵌套属性\u,允许\u销毁:true

@student.update\u属性(课程属性:[{id:student\u-course\u-association\u-id,\u-destroy:1}])

哪种版本的Rails。谢谢,安迪。这是Rails 3,beta 4。也许是时候试试RC了?我试着将回调移到学生模型中,在has\u many course\u学生协会上放置在添加后和删除前的回调。同样的行为!“添加后”会触发,但“删除前”不会触发。当前解决方法:我检测到当前课程列表中的更改。每一个改变的课程都会被重新设定种子。这是检测线(为我未来的自己):@student.courses.collect{c|c.id.to_s}.to|set^params[:student][:courseu id]。对于_setIn student.rb,我添加了:dependent=>:销毁到has_many:courseu学生,因此如果一个学生被销毁,那么课程学生也会被销毁,而不是反过来(尽管两者中任何一方的存在都没有意义)。我还将before_destroy改为after:allows_to,代码的行为也一样。我还没有尝试过RC,我也没有完全使用edge Rails。我使用RC4是因为Heroku目前支持它,我必须迁移几个开发人员。我希望在我自己检测哪些项目被删除之前,能找到一个简单的解决方法。我没有太多使用嵌套属性。
Dirty
是否与嵌套属性一起工作。我想这可能会使您自己更容易检测已删除的关联记录。可能类似于Parent.child.changed?在保存前称为
的方法中,如果需要,会执行删除操作。Jus