有没有一种方法可以更新辅助属性?

时间:2020-01-04 11:01:07

标签: ruby-on-rails

我目前正在研究Ruby on Rails(v5.2)项目,用于记录体育俱乐部的出勤情况。每个学生都属于一个付款计划,每个付款计划都有一个classes_amount。 Classes_amount是学生在再次付款之前可以参加的课程数。每个学生都有一个classes_remaining列来跟踪此情况。每次出勤后自动减少,每当他们付款时增加。

我要在更改学生的Payment_plan时自动更新该学生的classes_remaining属性。例如。如果学生想从付款计划A(5个班级)更改为付款计划B(10个班级),我希望他们的classes_remaining属性增加10。在我将学生分配给新的付款计划时,他们的classes_remaining值保持零。

这是我目前在更新方法中所拥有的:

def update
    @student = current_club.students.find_by(id: params[:id])
    classes_amount = @student.payment_plan.classes_amount
    logger.debug "Classes amount is currently: #{classes_amount}"
    if classes_amount.present?
        if @student.classes_remaining.present?
            @student.classes_remaining = @student.classes_remaining + classes_amount
        else
            @student.classes_remaining = classes_amount
        end
    else
        @student.classes_remaining = nil
    end
    if @student.update_attributes(student_params)
        flash[:success] = "Student details updated"
        redirect_to @student
    else
        @activities = current_club.activities.all
        render 'edit'
    end
end

有一个付款计划,其中没有classes_amount,因此if classes_amount.present?行。 我的调试消息显示Classes amount is currently:

当付款方式更改时,如何自动更新学生的“ classes_remaining”列?

1 个答案:

答案 0 :(得分:1)

使用ActiveModel :: Dirty,https://api.rubyonrails.org/classes/ActiveModel/Dirty.html

可能是最简单的

您只需要将此行添加到学生模型中即可:

## app/models/student.rb

class Student << ApplicationBase
  include ActiveModel::Dirty
  ...
  ...
end

这使您可以访问以下方法:

student.payment_plan_id_changed?
student.payment_plan_id_changed?(from: 1, to: 2)

如果尚未保存记录,则它们将返回true或false。这意味着您现在可以在模型中执行以下操作:

## app/models/student.rb

class Student << ApplicationBase
  include ActiveModel::Dirty
  define_attribute_methods :payment_plan_id

  before_save :handle_payment_plan_changes!

  private

  def handle_payment_plan_changes!
    return unless payment_plan_id_changed?

    if payment_plan_id_changed?(from: 1, to: 2)
      classes_remaining += 5
    elsif payment_plan_id_changed?(from: 2, to: 1)
      classes_remaining -= 5
    end
  end
end

值得注意的是,每次保存学生时,此before_save都会触发,因此请确保您希望在每次保存时都具有这种行为。如果这是一个问题,您可以随时在保存之前(将方法移出私有部分之后)从控制器手动调用handle_payment_plan_changes