Reputation: 1758
I'm using Rails 4. I have a class, Cart, which needs to be accessed within my application.
I want it accessed using the factory pattern:
class CartFactory
def self.obtain_cart_for_user(user)
...
end
end
I need this approach because sometimes, I want to return an existing cart and sometimes create a new one (based upon the age of the cart, its contents, whether the products in it are still available etc).
This is easy enough.
However, I also want to make sure some other future programmer doesn't instantiate a cart directly, or fetch one by any other means, including via model associations, such as:
Cart.new(...)
user.carts.new(...)
Cart.find(id)
Cart.find_by_attribute(blah: blah)
Cart.where(...).first
Is there any way to prevent that?
Upvotes: 2
Views: 1752
Reputation: 7101
Well, it's possible to make the constructor private:
private_class_method :new
And of course, you can try making the ActiveRecord query methods (.find
, .where
etc.) private as well. But to me that sounds like a good way to end up with erratic behaviour. If you were to go this route, make sure your app is thoroughly tested first.
Another route would be for Cart
not to extend ActiveRecord::Base
(which I'm assuming it does), and instead include only the parts you need, like ActiveRecord::Persistence
. If you are willing to dive in deep, check out the parts that are included in the source for ActiveRecord::Base
.
Edit: Still one option would be to make Cart
itself private within a module that only exposes CartFactory
. There's no built-in syntax for a "private class", but it's possible to achieve since Ruby classes are just regular objects. Again, no idea how well ActiveRecord would deal with that.
But lastly there is of course the question of whether you want to do this at all. In general, Ruby is not very good at protecting you from yourself. :) As expressed in the latter linked answer, documentation and trust go a long way.
Upvotes: 6