2

I have the following models:

class Price < ActiveRecord::Base 
  belongs_to :product
end

class Metric < ActiveRecord::Base
  belongs_to :price
  belongs_to :product
end

In my application, since a Product doesn't change but the price does, I add new prices instead to a Product. My thing is, what about if the price is measured by a metric unit, for example:

Broccoli is $1.50 per 2 LBs

This would make 3 attributes:

  1. $1.50 = :cost_per_metric_unit
  2. 2 = metric_unit_amount
  3. LB = :metric_unit

The scenario when adding a new price is you first..

  1. Select a Product (Product)
  2. Give the cost (Price)
  3. If its a metric unit based price, fill in those attributes.(Metric)

I am confused about the associations. I know Products can have many different Metrics but is this a :through association or does a Price belong to a Metric? Right now in my Metrics table I have the product_id and the price_id but is that right? I don't think one Price can have many different Metrics, only a Product would.

How would you set this up?

Thank you.

LearningRoR
  • 26,582
  • 22
  • 85
  • 150

1 Answers1

2

As Matthew Lehner pointed out, having Metric be its own table is an unnecessary abstraction. The product and the unit (what you call metric--which is a misnomer, I believe, and leading you down the wrong path), can live together in the same table. There is no point in allowing the units vary independently of product. Each product is measured in a specific unit that's immutable. For example, product A may be measured by weight, product B by volume and product C by length. It wouldn't make any sense at all to allow the flexibility to measure product A in any unit other than weight, and having this flexibility could be, in fact, a source unintended errors: If the units live in a separate table and are referred by foreign key, then they could be updated independently from the product, causing errors of the type where may become measurable in a non-sensical unit.

This is a case where "commonality/variablity" analysis helps determine the required relationships. Figure out what stays constant and what can vary. In your example, the relationship between product and unit price can vary, but the relationship between product and unit measure should be fixed. Record the price in terms of price per unit and store the unit measure with the product. Also I think it may be clearer to call the price "unit price" -- price per unit of measure that the product can be sold in.

I would design it like this:

class UnitPrice < ActiveRecord::Base 
  belongs_to :product      
end

class Product < ActiveRecord::Base
  UNITS = %w(kg lbs liters gallons floz oz meters inches feet count) # add here as needed
  has_one :unit_price

  validates :unit, :inclusion => {:in => UNITS}

  def price_quote(amount)
    unit_price * amount
  end
end

This way you could conceivably also support more than one unit price on a product, e.g. for volume discounts, sales offers, etc.

By the way, if the item is measured simply in count, rather than weight, volume, etc., then the unit is "count", e.g. 5 dinner plates, and you have a unit price for 1 dinner plate.

On another note, if you're storing price data, use Integers or Decimal types. Don't use floats. See this answer.

Community
  • 1
  • 1
Wolfram Arnold
  • 7,159
  • 5
  • 44
  • 64
  • Thanks for the answer Wolfram. I do have questions. What if Broccoli could be sold by pieces as well? Lets say I had 1 piece of Broccoli being sold at a picnic, it also sales at a store in pounds and in bulk for a business in kilograms. Is this still handled the same way? Also, could I just keep all this in my `Price` model and give my `Product` model `UNITS` still? – LearningRoR Jan 30 '12 at 11:27
  • 2
    @wrbg -- You can provide different prices, yes, but you'll still only have one unit. I think what you're talking about is a different product entry, e.g.: "scrap wood" measured in pounds, vs. "2x4 6 feet long" measured in counts. So you could have "bulk broccoli" in pieces (measured by count) and "broccoli" measures in pounds. Distinct products may make the most sense, as they may be handled, packaged, inventories differently as well. PS: If you liked my answer, please hit the "accept" check mark next to it. – Wolfram Arnold Jan 30 '12 at 19:50