【发布时间】:2014-03-13 17:45:15
【问题描述】:
假设我有一个大的复合公式来计算小部件的质量
quality = 0.4(factory_quality) + 0.3(1/days_since_manufacture) + 0.3(materials_quality)
这三个因素中的每一个都是函数本身,它们需要连接到工厂表,并且可能需要连接到带有材料的物料清单连接表,其中关联的记录是平均的或其他的。
在架构上,您将如何在 Rails 项目中管理它? a) 产生正确的查询和 b) 在 Rails 中管理代码的最佳做法是什么?
目前对于 sql,我在 FROM 语句中使用子查询:
SELECT *,
(0.4 * factory_quality + 0.3 * (1/days_since_manufacture) + 0.3 * materials_quality) AS quality
FROM (
SELECT *,
((factories.last_inspection_score + factories.variance_score)/2) AS factory_quality,
(now() - widgets.created_at) AS days_since_manufacture,
SUM(materials.quality_score) AS materials_quality
FROM widgets,
JOIN factories ON widget.factory_id = factories.id
JOIN bills_of_materials ON widget.id = bills_of_materials.widget_id
JOIN materials ON bills_of_materials.material_id = materials.id
GROUP BY widgets.id
) AS widgets;
在 Rails 中,我主要使用 ActiveRecord 来实现:
class Widget < ActiveRecord::Base
belongs_to :factory
has_many :bills_of_material
has_many :materials, through :bills_of_material
class << self
def with_quality
select([
"widgets.*",
"(0.4 * factory_quality + 0.3 * (1/days_since_manufacture) + 0.3 * materials_quality) AS quality"
].join(",")
.from("(#{subquery}) AS widgets")
end
private
def subquery
select([
"widgets.*",
"((factories.last_inspection_score + factories.variance_score)/2) AS factory_quality",
"(now() - widgets.created_at) AS days_since_manufacture",
"SUM(materials.quality_score) AS materials_quality"
].join(","))
.joins(:factory,:materials)
.group("widgets.id")
.to_sql
end
end
end
也就是说,我觉得我可以在 Postgres 中将其设为自定义函数,将所有这些 sql 移动到该函数中,迁移它,然后清理 rails 的样子
def with_scores
select("*,quality_score_func(id) AS quality")
end
或类似的东西,但我觉得通过数据库迁移来管理一个不断发展的公式将是一件很痛苦的事情,更不用说找出公式的当前形式是什么的任务是(也很难测试)。
其他人是如何解决这个问题的?有什么提示或建议吗?
【问题讨论】:
-
澄清一下,我并不是要避免使用 sql,而且出于性能原因,我相信计算属于数据库。我只是想知道是否有人开发了一种设计模式来清理这段代码。
标签: sql ruby-on-rails ruby postgresql activerecord