【问题标题】:Retroactive changes to user records (point reconciliation)对用户记录的追溯更改(积分对账)
【发布时间】:2023-03-19 19:03:01
【问题描述】:

我有三个模型:

  1. 课程
  2. 用户
  3. 课程完成

除了标题和内容之类的东西,每门课程还有一个分值。当用户完成一门课程时,他们将获得该课程的积分值,该积分值将添加到他们的total_points。 CourseCompletion 只是跟踪哪个用户完成了哪些课程(带有user_idcourse_idcompletion_date 列)。

此数据模型的一个弱点是,如果管理员用户在用户完成该课程之后编辑该课程的积分值,则该用户的积分不会更新。我需要一种方法来追溯地做到这一点。例如,如果用户完成一门课程并获得 10 分,然后管理员将课程更改为 20 分,则该用户最终应该有 20 分。我以前没有做过这种事情——最好的方法是什么?

我目前的计划是双重的。在第一部分中,我对 Course 和 CourseCompletion 模型进行了更改:

  1. 向 CourseCompletion 添加一个points_earned 列,以记录用户完成该课程所获得的积分。
  2. points_recently_changed 列添加到课程。如果课程的分数随时更新,请将此列设置为该课程的 true。 (see my related question)

在第二部分中,脚本或任务 (?) 每天运行一次并执行以下操作:

  1. 获取points_recently_changed 等于 true 的所有课程
  2. 查找这些课程的所有课程完成情况
  3. 计算 course.points 和 course_completion.points_earned 之间的差异
  4. 相应地更新相应用户的总积分
  5. 将 course.points_recently_updated 改回 false。

这种方法是否存在任何明显的问题,或者是否有“Rails 方式”来做这样的事情?

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4


    【解决方案1】:

    为什么不使用 ActiveRecord::Calculations 来获取整个相关课程的总分并将它们存储在列中。每次管理员更改课程点数时更新该列。

    您可以使用 ActiveRecord::Dirty 跟踪点的变化

    http://api.rubyonrails.org/classes/ActiveModel/Dirty.html

    并使用 Calculations 计算点数:

    http://api.rubyonrails.org/classes/ActiveRecord/Calculations.html

    作为一种可能的解决方案:

    class Course < ActiveRecord::Base
      before_save :update_user_points
    
      def update_user_points
        User.all.each {|user| user.update_points } if self.points_changed?
      end
    end
    
    class User < ActiveRecord::Base
    
      def update_points
        self.points = self.courses.sum(:points)
      end
    
    end
    

    建议:

    我不喜欢将点保存在数据库中,因为它是一个变量。我建议您在每次用户登录时进行计算,并将其保留为带有过期日期的缓存数字。所以必须每天重新计算。

    【讨论】:

    • 来自 ActiveRecord::Dirty
    • 这是一个有趣的方法。我试试看!
    • 添加了关于 Dirty 的信息。我希望它有效!给我一些反馈:P
    【解决方案2】:

    我尝试了 Jorge 的建议,但并不满意。我最终采用了类似的方法,在登录过程中重新计算用户的积分。

    用户.rb

    def recalculate_points
      new_course_points = self.course_completion_courses.sum(:worth)
      self.update_attribute(:points, self.course_completion_courses.sum(:worth))
      self.save
    end
    

    session_helper.rb

    def sign_in(user)
      ...
      current_user.recalculate_points
    end
    

    点仍然存储在用户表中 - 简单地缓存它们是行不通的,因为我做了一些报告,需要将该信息保留在数据库中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多