0

DB に 2 つのテーブルがあります。userstrackers

ご想像のとおり、それぞれTrackerがテーブルにuser_id関連していusersます。

このアプリのコンテキストは、チーム ベースのタイム トラッキング ソリューションの一部であるということです。その一環として、これまでに追跡した合計時間でユーザーを並べ替え、この合計を画面に表示する必要があります。

Trackerそのため、 aが保存されるたびに、オブジェクトからとの値を取得するbefore_saveコールバックを起動し、トラッカーの時間を秒単位で簡単に取得できると考えました。結果は に保存されます。この部分が機能し、DB で計算値を確認できます。start_timeend_timeTracker(end_time - start_time).to_iTracker.tracked_time

ユーザーごとのすべてのTrackerインスタンスの値の合計結果を保存する必要があります。次に、この値をテーブルの列に保存して、データベースからこれを引き出して結果を並べ替えることができるようにします (考えてください: ほとんどアクティブなユーザー、最もアクティブでないユーザー、トップ 10)。tracked_timeuserstracked_time

ただし、これbefore_save :calculate_tracked_time, if: :finished?, unless: :admin?を呼び出そうとすると、単にActiveRecord::RecordNotSavedエラーが発生します。

Userモジュール内にいる間はモデルの値を保存できないようTrackerです…しかし、必要なことを行う理由や他の方法についての手がかりがありません。

これを機能させる(またはおそらくより良く機能させる)方法についての考えは大歓迎です。

:tracked_timeUser型番は記載してあり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

読んでくれてありがとう。

4

1 に答える 1

1

フィールドを更新して保存を呼び出す代わりに、update_column を使用してみてください。

user.update_column(:tracked_time, total_time)

update_column はコールバック (または検証) を呼び出しません。そのため、注意が必要です。コールバックは、既にコールバック中の場合に保存を妨げる可能性があります。

于 2012-08-09T09:00:43.137 に答える