If there is a calculation process, you will create a method in the related ActiveRecord model [^ 1].
product.rb
class Product < ApplicationRecord
def billing_price
price * consumption_tax_rate
end
def consumption_tax_rate
#Return sales tax rate
end
end
[^ 1]: I'm omitting it because it's not the main subject, but let's calculate floating point numbers properly! => [Ruby] Use Big Decimal for sales tax calculation
I don't feel that much of a problem when calculating the tax-included amount. However, when discounts are started in campaigns or the discount conditions become complicated, the product class seems to be a monetary calculation class.
product.rb
class Product < ApplicationRecord
def billing_price
campaign_discounted_price * consumption_tax_rate
end
def consumption_tax_rate
#Return sales tax rate
end
def campaign_discounted_price
#Return the price to which the campaign was applied
#If the campaign becomes complicated, this method becomes complicated,
#The number of methods that can only be called from this method will increase!
end
end
If nothing is done, it will become a Fat Model.
Create a class to calculate the consumption tax and a class to calculate the campaign discount.
consumption_tax_calc_rule.rb
class ConsumptionTaxCalcRule
attr_accessor :price, :product_type
# product_type is the information to decide whether to apply the reduced tax rate (please keep in mind)
def initialize(price, product_type)
self.price = price
self.product_type = product_type
end
def tax_included_price
price * tax_rate
end
def tax_rate
#Return sales tax rate
end
end
campaign_discount_calc_rule.rb
class CampaignDiscountCalcRule
attr_accessor :price, :campaigns
#campaigns is information for campaign discounts (please keep in mind)
def initialize(price, campaigns)
self.price = price
self.campaigns = campaigns
end
def discounted_price
#Even if more methods are called only from this method
#In the campaign discount calculation class
#Nothing is wrong because there are only more methods for campaign discounts!
end
end
For the product class, just use the CalcRule class.
product.rb
class Product < ApplicationRecord
def billing_price
discount_rule = CampaignDiscountCalcRule.new(price, campaigns)
tax_rule = ConsumptionTaxCalcRule.new(discount_rule.discounted_price, product_type)
tax_rule.tax_included_price
end
end
Now, even if the sales tax changes or the campaign changes, you only have to check the CalcRule class!
This entry is for Business Rules (https://linyclar.github.io/software_development/requirements_analysis_driven_desgin/#%E3%83) in Requirements Analysis Driven Design (https://linyclar.github.io/software_development/requirements_analysis_driven_desgin/) % 93% E3% 82% B8% E3% 83% 8D% E3% 82% B9% E3% 83% AB% E3% 83% BC% E3% 83% AB) Shows a concrete example and general-purpose content It was rewritten to. It's a long story, but it's a story about DDD-like things in Rails.
Recommended Posts