Reputation: 4835
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?
Upvotes: 2
Views: 598
Reputation: 11921
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.
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:
If you go this route, the ActiveRecord callbacks like before_save might be useful. Good luck.
Upvotes: 1
Reputation: 21794
If I understand your question correctly, I believe you are looking for Polymorphic Associations.
Example:
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
Upvotes: 0