Rails-可扩展的计算模型 [英] Rails - Scalable calculation model

查看:68
本文介绍了Rails-可扩展的计算模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前在Rails应用程序中具有一个计算结构,该结构具有模型metricoperandoperation_type.

当前,metric模型具有许多operands,并且可以基于operation_type执行计算(例如,求和,乘等),并且每个operand都定义为向右或向左(即,因此,如果运算是除法运算,则可以识别分子和分母.

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

为了使其具有可伸缩性,需要允许操作数 某种属性或上一操作的结果,即操作数可以是度量. >

我提供了一个当前模型外观的图表:

有人可以协助我以最优雅的方式允许操作数成为实际操作数或其他度量标准吗?

谢谢!

到目前为止,似乎仅基于唯一的答案可能就是多态关联,但是答案是如此简短,我不知道如何以这种方式使用它们-任何人都可以阐述吗? /p>

好吧,我想我要走了-基本上我目前有一个指标,该指标有has_many个操作数和一个has_many度量值.我需要一个多态自我联接,其中一个度量标准也可以有许多度量标准-我是否需要将其称为"calculated_metrics",以便度量标准模型可以使用其自身?这将使我处于一个度量标准具有多个操作数,而一个度量标准具有许多calculated_metrics的情况.

我已经更新了我的模型,如下所示,如果有人批评这是否是解决问题的好方法,我将不胜感激.您会注意到,我添加了一个名为calculated_metric的模型,该模型实际上是其他度量标准的持有者-即可以使用两个操作数或一个操作数与calculated_metric的组合来计算度量.

为任何可以向我展示详细的方法的人提供了赏金.

赏金计划仍在争夺中;尽管下面提供的答案很详细,但我正在寻找解决此问题的最佳方法,而不是寻求解决问题的替代方法(即,请让我知道解决问题的最佳方法,而不是寻找避开问题的方法,因为我需要此功能).谢谢!

对此没有引起足够的重视-赏金增加会有所帮助,还是这个问题不是赛跑者?

解决方案

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

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

RDBMS确实似乎不是这项工作的正确工具.

您可以将表达式存储为字符串,然后在从文件或数据库中加载字符串时将其解析为表达式树.有很多示例说明如何编写表达式解析器.

因此,以Ruby和Rails的术语来表达.我将执行以下操作:

  1. 将组成表达式树的大多数类制作成不扩展的普通旧Ruby类 ActiveRecord.
  2. 在每个这些类中实现to_s,因此,如果将to_s发送到表达式树的根,则将得到表达式的格式正确的字符串表示形式.
  3. 实现一个ExpressionParser或ExpressionBuilder或ExpressionFactory(使用您喜欢的任何术语),它们可以从字符串创建表达式树.
  4. 然后,如果某些ActiveRecord模型曾经指向它专有"拥有的指标,则可以使其指向内存中的表达式树,但在保存自身时通过to_s来存储字符串表示形式.
  5. li>
  6. 如果几个ActiveRecord模型在旧设计中指向相同(共享)表达式,则必须为SharedExpressions创建一个类,该类使用字符串作为其持久表示形式,然后将AciveRecords更改为指向新的共享表达.

如果您走这条路线,ActiveRecord回调(例如before_save)可能会很有用.祝你好运.

I currently have a calculation structure in my rails app that has models metric, operand and operation_type.

Presently, the metric model has many operands, and can perform calculations based on the operation_type (e.g. sum, multiply, etc.), and each operand is defined as being right or left (i.e. so that if the operation is division, the numerator and denominator can be identified).

Presently, an operand is always an attribute of some model, e.g. @customer.sales.selling_price.sum.

In order to make this scalable, in need to allow an operand to be either an attribute of some kind, or the results of a previous operation, i.e. an operand can be a metric.

I have included a diagram of how my models currently look:

Can anyone assist me with the most elegant way of allowing an operand to be an actual operand, or another metric?

Thanks!

EDIT: It seems based on the only answer so far that perhaps polymorphic associations are the way to go on this, but the answer is so brief I have no idea how they could be used in this way - can anyone elaborate?

EDIT 2: OK, I think I'm getting somewhere - essentially i presently have a metric, which has_many operands, and an operand has_many metrics. I need a polymorphic self join, where a metric can also have many metrics - do I need to call this something else, perhaps calculated_metrics, so that the metric model can use itself? That would leave me with a situation where a metric has_many operands, and a metric has many calculated_metrics.

EDIT 3: I have updated my models as below, and would appreciate any critiques regarding whether this is a good way to approach the problem. You will note that I have added a model called calculated_metric that is essentially a holder for other metrics - i.e. a metric can be calculated using two operands, or a combination of an operand and a calculated_metric.

EDIT 4: Bounty added for anyone who can show me a detailed rails-y way of doing this.

EDIT 5: Bounty is still up for grabs; while the answer provided below is detailed, I am looking for the best way to do this, rather than alternative ways to approach the issue (i.e. please let me know the best way to tackle the issue, rather than looking for ways to sidestep it, as I need this functionality). Thanks!

Edit 6: Not getting much attention on this - would an increased bounty help, or is this question just not a runner?

解决方案

Consider stepping back and asking yourself if you really need to tear apart your expressions, and store them piece by piece in a relational database.

  • Does that really make sense for your purposes?
  • Are other applications going to query the underlying tables holding expression fragments?
  • Are you going to generate reports that show how often each operator is used?
  • Or are you using a relational database to store expressions just because that's most familiar?

A RDBMS really doesn't seem to be the right tool for this job.

You could store your expressions as strings and then parse them into expression trees as you load the strings from a file or a database. There are plenty of examples showing how to write an expression parser.

So to put it in Ruby and Rails terms. I'd do the following:

  1. Make most of the classes that comprise expression trees into plain old Ruby classes that do not extend ActiveRecord.
  2. Implement to_s in each of those classes, so that if you send to_s to the root of an expression tree, you'll get a well formed string representation of the expression in return.
  3. Implement an ExpressionParser or ExpressionBuilder or ExpressionFactory (use whatever term you like) that can create expression trees from a string.
  4. Then if some ActiveRecord model used to point to a metric that it "owned" exclusively, you can have it point to an expression tree in memory, but have it store the string representation (via to_s) when saving itself.
  5. If several ActiveRecord models pointed to the same (shared) expression in the old design, then you'll have to create a class for SharedExpressions that uses a string for it's persistent representation, and then change The AciveRecords to point to the new SharedExpression.

If you go this route, the ActiveRecord callbacks like before_save might be useful. Good luck.

这篇关于Rails-可扩展的计算模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆