我目前正在研究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”列?
答案 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
。