【问题标题】:Rails - Scalable calculation modelRails - 可扩展的计算模型
【发布时间】:2012-07-04 19:53:38
【问题描述】:

我目前在我的 Rails 应用程序中有一个计算结构,其模型为 metricoperandoperation_type

目前metric模型有很多operands,可以根据operation_type进行计算(如求和、乘法等),每个operand定义为右或左(即这样如果运算是除法,就可以识别出分子和分母)。

目前,操作数始终是某个模型的属性,例如@customer.sales.selling_price.sum.

为了使其可扩展,需要允许操作数或者是某种属性,或者是先前操作的结果,即操作数可以是度量。 p>

我已经附上了我的模型当前外观的图表:

谁能帮助我以最优雅的方式让操作数成为实际操作数或其他指标?

谢谢!

编辑:似乎基于迄今为止唯一的答案,也许多态关联是解决这个问题的方法,但答案是如此简短,我不知道如何以这种方式使用它们 - 任何人都可以详细说明吗?

编辑 2:好的,我想我到了某个地方 - 基本上我现在有一个指标,它有一个操作数,一个操作数有一个指标。我需要一个多态自联接,其中一个指标也可以有很多指标——我是否需要将其称为其他东西,也许是计算的_metrics,以便指标模型可以使用自己?这会让我遇到一个指标有很多操作数,而一个指标有很多计算指标的情况。

编辑 3:我已经更新了我的模型,如下所示,如果对这是否是解决问题的好方法提出任何批评,我将不胜感激。您会注意到,我添加了一个名为 calculated_metric 的模型,它本质上是其他指标的持有者 - 即可以使用两个操作数或一个操作数和一个计算指标的组合来计算一个指标。

编辑 4:为任何可以向我展示详细的 rails-y 方法的人添加赏金。

编辑 5:赏金仍在等待中;虽然下面提供的答案很详细,但我正在寻找最好的方法,而不是解决问题的替代方法(即请让我知道解决问题的最佳方法,而不是寻找回避它的方法,因为我需要这个功能)。谢谢!

编辑 6:对此没有引起太多关注 - 增加赏金会有所帮助,还是这个问题不是跑步者?

【问题讨论】:

  • 没有想法?如果我试图做的事情是不可能/明智的,我会感激任何 cmets。
  • 请参阅问题中的编辑 3 以获取最新更新。
  • 我将为任何可以表明此方法是否是最佳选择,或者我是否应该自我引用度量模型或类似方法的答案添加赏金;无论是最“rails-esque”的方式。
  • 赏金仍然有效 4 天,但看起来我需要在这一次上放弃它 - 希望有人能在周末提供帮助。谢谢!

标签: ruby-on-rails database ruby-on-rails-3 model-view-controller model


【解决方案1】:

如果我正确理解您的问题,我相信您正在寻找Polymorphic Associations

例子:

class Metric < ActiveRecord::Base
   belongs_to :calculable, :polymorphic => true
   has_many :operations, :as => calculable
end

class Operand < ActiveRecord::Base
   belongs_to :calculable, :polymorphic => true
end

【讨论】:

  • 我知道多态关联可用于允许模型属于其他两个模型中的任何一个,但我不清楚在这种情况下如何使用它,模型本质上需要能够使用自己(度量使用以下任何一种执行计算:两个操作数,一个操作数和一个度量,或两个其他度量)。也许您可以详细说明一个指标如何使用另一个指标?
  • 请参阅该链接的底部 2.10 自联接。没有什么能阻止指标与自身建立关系。
【解决方案2】:

考虑退后一步,问问自己是否真的需要拆分表达式,并将它们逐个存储在关系数据库中。

  • 这对您的目的真的有意义吗?
  • 其他应用程序是否会查询包含表达式片段的基础表?
  • 您是否要生成报告以显示每个操作员的频率? 用过?
  • 或者您是否因为最熟悉的表达式而使用关系数据库来存储表达式?

RDBMS 似乎真的不是这项工作的正确工具。

您可以将表达式存储为字符串,然后在从文件或数据库加载字符串时将它们解析为表达式树。有很多例子展示了如何编写表达式解析器。

所以用 Ruby 和 Rails 的术语来说。我会做以下事情:

  1. 将构成表达式树的大多数类变成不扩展的普通旧 Ruby 类 活动记录。
  2. 在每个类中实现 to_s,这样如果您将 to_s 发送到表达式树的根,您将获得表达式的格式良好的字符串表示形式作为回报。
  3. 实现可以从字符串创建表达式树的 ExpressionParser 或 ExpressionBuilder 或 ExpressionFactory(使用您喜欢的任何术语)。
  4. 然后,如果某个 ActiveRecord 模型曾经指向它专门“拥有”的指标,您可以让它指向内存中的表达式树,但在保存自己时让它存储字符串表示形式(通过 to_s)。李>
  5. 如果多个 ActiveRecord 模型在旧设计中指向同一个(共享)表达式,那么您必须为 SharedExpressions 创建一个类,该类使用字符串作为其持久表示,然后将 AciveRecords 更改为指向新的共享表达式。

如果你走这条路,像 before_save 这样的 ActiveRecord 回调可能会有用。祝你好运。

【讨论】:

  • 感谢您的信息 - 我考虑过这是否真的有必要(请参阅我个人资料中的其他问题),并得出结论认为这可能是最好的方法,因为用户需要能够调整现有指标或创建新指标。确实会有基于使用底层算子的报告,因为每个算子实际上都是来自供应商的产品(为了简单起见),而商业模式意味着我们需要知道查询的是什么。根据订阅级别,可访问的指标也可能存在限制,因此需要此级别的粒度。
猜你喜欢
  • 1970-01-01
  • 2019-02-23
  • 2015-10-15
  • 2013-06-17
  • 2011-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-06
相关资源
最近更新 更多