【问题标题】:Active Record callbacks with has_many association具有 has_many 关联的 Active Record 回调
【发布时间】:2017-06-07 18:13:16
【问题描述】:

我想在每次将子对象添加到父对象(has_many 关联)时运行before_saveafter_add 回调。在回调中,我想根据所有子级(课程)的end_date 属性在父级(队列)上设置end_date 属性。

class Cohort < ActiveRecord::Base
  has_many :courses   
  before_save :update_end_date

  def update_end_date
    self.end_date = courses.order(:end_date).last.try(:end_date)
  end
end

我遇到的问题是课程尚未在before_save 回调中保存到数据库中,因此courses.order(:end_date) 不会返回新添加的课程。

我可以使用几种解决方法(例如,使用 Ruby courses.sort_by 方法或使用 after_saveupdate),但我的印象是,如果可能的话,使用 Active Record order 方法会更好在效率和最佳实践方面。有没有办法在before_save 中使用 Active Record 来做到这一点,或者什么可能是最好的做法?这似乎会出现很多,但我很难找到适合我的解决方案,所以我觉得我一定是想错了。谢谢!

【问题讨论】:

    标签: ruby-on-rails-4 activerecord callback associations has-many


    【解决方案1】:

    如果课程的结束日期晚于同类群组的结束日期,您可以对可能会更新同类群组的课程进行事后保存。以及课程的后销毁,它告诉队列更新其结束日期以对应于剩余的课程。

    class Course < ActiveRecord::Base
      belongs_to :cohort
      after_save :maybe_update_cohort_end_date
      after_destroy :update_cohort_end_date
    
      def maybe_update_cohort_end_date
        if cohort && self.end_date > cohort.end_date
          cohort.end_date = self.end_date
          cohort.save
        end
      end
    
      def update_cohort_end_date
        cohort.update_end_date if cohort
      end
    end
    
    class Cohort < ActiveRecord::Base
      has_many :courses
    
      def update_end_date
        self.end_date = courses.order(:end_date).last.try(:end_date)
      end
    end
    

    这样,您只有在新课程或更新课程的结束日期会更改同类群组结束日期时才进行更新。但如果课程被删除,也会捕捉到,然后检查结束日期应该是什么

    【讨论】:

    • 把它放在孩子身上是有道理的(当然)。我有点希望将逻辑放在父级(队列)中,因为这主要与队列有关,而且并非所有课程都有队列。但是,如果父母没有干净的方法来做到这一点,我当然可以把它放在孩子身上。谢谢!
    • 如果课程可以在没有群组的情况下存在,则回调将需要对此进行检查。在尝试更新之前更新了我的答案以检查同类群组是否存在。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-01
    • 1970-01-01
    • 2012-10-24
    • 1970-01-01
    • 2011-11-20
    • 1970-01-01
    相关资源
    最近更新 更多