Hi,
I recently performed a major rewrite of my app to provide better
encapsulation and more descriptive behavior for my models.
But I also encountered very often a dilemma: does the logic I am writing
belong to the class, or does it belong to an instance?
I am running an ecommerce website, so I have the following models:
User(id, name, …)
Order(id, user_id, status, amount)
Item(id, order_id, product_id, quantity)
Product(id, price, title, …)
Now I’d like to know if a given User has purchased a given Product.
So I fetch my user and product objects
user = User.find_by_name(‘Fernando’)
product = Product.find_by_title(‘The book of Awesome’)
Then, here is my problem. How would you search if the book was purchased
by the user? There are few ways of doing it:
- User#find_if_user_purchased_product?(product_id)
And then the search makes a join with Item and Order, but it introduces
the state of the Order in the condition, it could be ‘paid’, ‘unpaid’.
And here is my problem: I recently migrated from an integer state (i.e:
paid = 0, unpaid = 5) to strings. And that logic is in the User model,
but a User shouldn’t be aware about how Order handles its payment
status.
Therefore this might mean that I should create a class method:
Order.find_paid_order_for_product_by_user(product_id, user_id)
This only has to know about the product_id and the user_id. Now this
means that my User#find_if_user_purchased_product(product_id) code
becomes something like:
def find_if_user_purchased_product?(product_id)
!!Order.find_paid_order_for_product_by_user(product_id, self.id)
end
Doesn’t it seem stupid that 1 method under hood, simply calls another
method? Don’t I have a problem of how I am searching if my user has
purchased this product?
How would you handle such problem? It’s not only related to my ecommerce
shop, it could be anything where a DB search is made across 3 tables of
relationship.