【问题标题】:Can I save a different AR object from the one I'm in via a callback in RoR3?我可以通过 RoR3 中的回调保存与我所在的 AR 对象不同的 AR 对象吗?
【发布时间】:2012-08-09 08:33:01
【问题描述】:

我的数据库中有 2 个表。 userstrackers

如您所料,每个Tracker 都有一个与users 表相关的user_id

此应用的背景是它是基于团队的时间跟踪解决方案的一部分。作为其中的一部分,我需要按用户迄今为止跟踪的总时间对用户进行排序,并在屏幕上显示该总时间。

所以我认为每当保存Tracker 时,我都会触发before_save 回调,该回调从Tracker 对象中获取start_timeend_time 值并执行简单的(end_time - start_time).to_i 来获取时间跟踪器在几秒钟内。结果保存到Tracker.tracked_time。这部分有效,我可以在数据库中看到计算出的值。

我现在需要保存每个用户的所有Tracker 实例的tracked_time 值的总结果,然后我想将此值存储到tracked_time 列中的users 表中,以便我可以将其从数据库中提取出来并按(想想:最活跃的用户、最不活跃的用户、前 10 名)对结果进行排序。

但是,当我尝试调用此 before_save :calculate_tracked_time, if: :finished?, unless: :admin? 时,我只会收到 ActiveRecord::RecordNotSaved 错误。

Tracker 模块中时,我似乎无法在 User 模型上保存值……但我不知道为什么或如何做我需要的事情。

任何关于如何使这项工作(或工作更好)的想法将不胜感激。

哦,User 模型上的 :tracked_time 列在 attr_accessible 中,因此可以写入。

下面是Tracker 模型,如果需要我也可以发布User 模型。

class Tracker < ActiveRecord::Base
  attr_accessible :running, :start_time, :end_time, :tracked_time, :intention, :achievement
  belongs_to :user

  before_save :calculate_tracked_time, if: :finished?, unless: :admin?

  validates :user_id,   presence: true
  validates :intention, presence: true,
                        length: { minimum: 5 }

  default_scope order: 'trackers.created_at DESC'

  private

    def finished?
      # Only save the total amount of time elapsed if we have
      # a start_time AND end_time for this object.
      !self.end_time.nil?
    end

    def admin?
      # Don't calculate totals for the admin user.
      User.find_by_id( self.user_id ).admin?
    end

    def calculate_tracked_time

      # write the tracker's tracked time value in seconds
      self.tracked_time = ( self.end_time - self.start_time ).to_i

      # update the user's tracked time total
      user = User.find_by_id( self.user_id )
      # calculate time from all trackers this user has
      total_time = 0
      user.trackers.each { |t| total_time += t.tracked_time }
      # this log correctly prints the correct figures.
      p "Total Time for user (#{self.user_id}): #{total_time}"
      # store it to the user's :tracked_time db column
      user.tracked_time = total_time
      # save !!! Errors out.
      user.save
    end

end

感谢阅读。

【问题讨论】:

  • 您是否尝试过使用 user.update_column(:tracked_time, total_time) 而不是更新和调用保存? update_column 不调用任何回调,这可能会给您带来问题。
  • 哇,成功了!它现在按预期工作。谢谢你。想要将此作为答案发布以便我接受吗?
  • 已经完成谢谢,很高兴它成功了。 :)

标签: ruby-on-rails database ruby-on-rails-3 activerecord callback


【解决方案1】:

不要更新字段并调用保存,而是尝试使用 update_column:

user.update_column(:tracked_time, total_time)

update_column 不调用任何回调(或验证,因此您需要小心)。当您已经在回调中时,回调可能会阻止保存。

【讨论】:

    猜你喜欢
    • 2023-01-31
    • 2016-05-29
    • 2022-10-08
    • 2018-02-28
    • 1970-01-01
    • 1970-01-01
    • 2015-05-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多