ruby-on-rails - 有没有办法更新次要属性?
问题描述
我目前正在开发一个 Ruby on Rails (v5.2) 项目,用于记录体育俱乐部的出席情况。每个学生都属于一个 payment_plan,每个 payment_plan 都有一个 classes_amount。Classes_amount 是学生在再次付款之前能够参加的课程数量。每个学生都有一个 classes_remaining 列来跟踪这一点。每次出勤后自动减少,每次付款后自动增加。
我想在更改学生的 payment_plan 时自动更新学生的 classes_remaining 属性。例如,如果学生想从 payment_plan A(5 个班级)更改为 payment_plan 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
有一个 payment_plan 没有 classes_amount,因此这if classes_amount.present?
条线。我的调试消息显示Classes amount is currently:
当学生的 payment_plan 发生变化时,如何自动更新学生的 classes_remaining 列?
解决方案
使用 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
在保存之前从控制器手动调用(在将方法移出私有部分之后)。
推荐阅读
- java - 解析 ZonedDateTime.parse 忽略偏移量
- sql - 将值声明为表格
- python - Django:可为空的 DateTimeField 填充当前时间戳?
- java - 如果我们使用 signInAnonimously 可以重新连接用户吗?
- google-chrome - 设置 TWA 并部署到存储后,URL 栏仍然显示
- maven - codehaus.mojo build helper 插件的目标“add-resource”与 maven install 插件的目标“install-file”有什么区别?
- javascript - regex.test() 冻结网页
- java - Scanner.hasNext() 在线编译时返回 false,但在 eclipse 上编译时返回 true
- javascript - Redux reducer 作为纯函数
- pdf - Ghostscript:将带有图片的PDF从RGB转换为灰色