The satisfaction of Rails
More work on XChain. In some spare hours on the weekend I implemented the basic structure of price catalogues for products. I can’t tell you how long this took when previously doing it in PHP a few years back! (or even worse ASP a few years further back still). I’m sold on BDD, it was so quick to bang this out starting with the spec it first approach, mainly because all you need to do is ‘rake spec’, and bingo your code is tested…
As follows, note code is cut down a little, but you get the picture:
# A product itself does not contain any price information, it has many price's in a 'pricing' model, that is linked # to price types, eg "Standard Distributor" "Standard Retail" class Product < ActiveRecord::Base has_many :pricings has_many :price_types, :through => :pricings belongs_to :order_line end #The pricing table, not only links to a product and price_type, it also has a discount #model associated with it.. class Pricing < ActiveRecord::Base set_table_name 'pricing' belongs_to :product belongs_to :price_type belongs_to :discount end
# discount linked to the pricing, and discount tables to enable volume based discounting. class Discount < ActiveRecord::Base has_many :pricing has_many :discount_tables, :order => "qty ASC" #note that I don't want to do queries every time I ask get_discount, so I just iterate over the # tables to find the discount, rather than doing a find each time. def get_discount(qty) discount_tables.each do |dt| return dt.discount_applied if qty <= dt.qty end return discount_tables.last.discount_applied end end # In order to calculate price, we need to determine the pricing model for the order (taken from price type) # then look up the unit price for the product according to the price type # finally get the discount for the volume at that price type. class OrderLine < ActiveRecord::Base belongs_to :order belongs_to :product def get_price(price_type) @pricing = product.get_pricing(price_type) price_as_ordered = ( get_unit_price * qty_ordered ) * get_discount end protected def get_unit_price @pricing.get_unit_price() end def get_discount @pricing.discount.get_discount(self.qty_ordered) end
You feel like you accomplished something when you sit down to work for a few hours and you get this…
===================== rowans-computer:~/work/xchain rowan$ rake spec; (in /Users/rowan/work/xchain) DiscountTable - should be valid Discount when loading existing discount - should return a max discount of 0.25 for a quantity of 10000 - should return a discount of 1 for a quantity of 20 - should return a discount of 1.5 for a quantity of 5 - should respond to get discount - should have a discount table - should have a name - should belong to a pricing Order when finding existing order - should have a customer - should have a billing address - should have 3 order lines - should have a purchase order number - should have id = 1 Order with a single, invalid order line added - should after changing the quantity be able to be saved - should not be able to be saved as it has incorrect quantity - should calculate to a correct amount Order new draft order - should be in the order collection list - should belong to the correct customer - should have an associated user who created it - should be able to have it's address changed - should be able to be changed to a new status Order when creating a new order - should when valid and saved, have one order status history item - should be able to have an order line added - should throw an error that it doesn't have line items - should calculate return 0 dollars - should have a default price type matching customer price type - should be able to prefill an address - should default to draft status - should be able to instantiate OrderStatus using a draft order status a super user - should have a list of all available statuses OrderStatus using a draft order status with no super user - should not have all statuses available - should have a list of next available status, when flow next is false, only including itself and the next higher status OrderStatus - should be able to find standard statuses Product when using Product ID 1 - should be valid OrderLine with valid order line - should return correct discount levels (NOT IMPLEMENTED) - should after changing qty return a different price (NOT IMPLEMENTED) - should return a price of for x price type and y qty with a discountable price type - should return a price of for x price type and y qty with a non-discountable price type - should respond to get_price - should be valid Finished in 1.72758 seconds 40 examples, 0 failures, 2 not implemented

2 Comments, Comment or Ping
meekish
“…all you need to do is ‘rake spec’”
In case you haven’t already, you should take a look at autotest. It supports Rails out of the box. I find it indespensible in the BDD process.
XChain is looking pretty sweet.
Aug 14th, 2007
admin
Yep I’ve had autotest running, not sure I’m a fan. I prefer the actual thought process of saying ‘right this should work’…
Aug 14th, 2007
Reply to “The satisfaction of Rails”