如何使用 rails 将一条记录中多列的计算结果更新到 postgresql 数据库中
how to update a computed result of several columns in one record into postgresql database with rails
我有一个名为 "Scores" 的 table,它有 4 列,"first"、"second"、"third" 和 "average" 用于保存用户评分记录。
当用户最初创建记录时,他可以将 "average" 列留空。然后他可以稍后编辑所有 3 个乐谱。
编辑后,用户可以在他的显示页面中看到计算的平均值(或总和,或任何计算结果。),因为我有
默认显示
@ave = (@score.first + @score.second + @score.third)/3
结束
但是,@ave 不在数据库中,如何将@ave 更新到我数据库的"average" 列中?
理想情况下,最好在更新到数据库之前进行计算,这样4个值可以一起更新到数据库。它可能与活动记录回调有关,但我不知道该怎么做。
第二种方法,我想我需要在数据库中有一个 "trigger" 以便它可以在其他 3 列更新后立即计算和更新 "average" 列。如果您是这样做的,请告诉我与解决方案 1 相比的优势。
最后一种方法,因为用户已经知道他的显示页面中的平均值,所以我不必立即将计算出的平均值更新到 "average" 列中。我想我可以把它留给 delayed_job 或后台工作。如果你是这样做的,请告诉我怎么做。
提前致谢!(ruby 2.3, rails 5.0.1, postgresql 9.5
想法 1 和 2 是完全有效的方法。想法 3 有点矫枉过正,我强烈建议不要采用这种方法。
在想法 1 中,您需要做的(使用任何语言)只需查看输入的每个单独值(不包括平均值)并生成要包含在插入语句中的平均值。就这么简单。
想法2需要触发如下:
CREATE OR REPLACE FUNCTION update_average()
RETURNS trigger AS
$BODY$
BEGIN
NEW.AVERAGE=(NEW.first+NEW.second+NEW.third)/3;
RETURN NEW;
END;
$BODY$
然后在更新或插入 table 时将其分配给 运行:
CREATE TRIGGER last_name_changes
BEFORE INSERT or UPDATE
ON scores
FOR EACH ROW
EXECUTE PROCEDURE update_average();
除非您出于某种原因确实需要存储在数据库中的平均值,否则我会向 Score 模型添加一个属性:
def average
(first + second + third)/3.0
end
如果一个或多个可能不存在,我会:
def average
actual_scores = [first, second, third].compact
return nil if actual_scores.empty?
actual_scores.sum / actual_scores.size
end
如果您确实需要保存平均值,那么我会添加一个 before_validate 回调:
before_validation do
self.average = (first + second + third)/3.0
end
我有一个名为 "Scores" 的 table,它有 4 列,"first"、"second"、"third" 和 "average" 用于保存用户评分记录。
当用户最初创建记录时,他可以将 "average" 列留空。然后他可以稍后编辑所有 3 个乐谱。
编辑后,用户可以在他的显示页面中看到计算的平均值(或总和,或任何计算结果。),因为我有
默认显示 @ave = (@score.first + @score.second + @score.third)/3 结束
但是,@ave 不在数据库中,如何将@ave 更新到我数据库的"average" 列中?
理想情况下,最好在更新到数据库之前进行计算,这样4个值可以一起更新到数据库。它可能与活动记录回调有关,但我不知道该怎么做。
第二种方法,我想我需要在数据库中有一个 "trigger" 以便它可以在其他 3 列更新后立即计算和更新 "average" 列。如果您是这样做的,请告诉我与解决方案 1 相比的优势。
最后一种方法,因为用户已经知道他的显示页面中的平均值,所以我不必立即将计算出的平均值更新到 "average" 列中。我想我可以把它留给 delayed_job 或后台工作。如果你是这样做的,请告诉我怎么做。
提前致谢!(ruby 2.3, rails 5.0.1, postgresql 9.5
想法 1 和 2 是完全有效的方法。想法 3 有点矫枉过正,我强烈建议不要采用这种方法。
在想法 1 中,您需要做的(使用任何语言)只需查看输入的每个单独值(不包括平均值)并生成要包含在插入语句中的平均值。就这么简单。
想法2需要触发如下:
CREATE OR REPLACE FUNCTION update_average()
RETURNS trigger AS
$BODY$
BEGIN
NEW.AVERAGE=(NEW.first+NEW.second+NEW.third)/3;
RETURN NEW;
END;
$BODY$
然后在更新或插入 table 时将其分配给 运行:
CREATE TRIGGER last_name_changes
BEFORE INSERT or UPDATE
ON scores
FOR EACH ROW
EXECUTE PROCEDURE update_average();
除非您出于某种原因确实需要存储在数据库中的平均值,否则我会向 Score 模型添加一个属性:
def average
(first + second + third)/3.0
end
如果一个或多个可能不存在,我会:
def average
actual_scores = [first, second, third].compact
return nil if actual_scores.empty?
actual_scores.sum / actual_scores.size
end
如果您确实需要保存平均值,那么我会添加一个 before_validate 回调:
before_validation do
self.average = (first + second + third)/3.0
end