Cam Price-Austin
Cam Price-Austin

Reputation: 1758

Rails - Force model to be created via factory method

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

Answers (1)

lime
lime

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

Related Questions