ActorModel pattern in Rails
Something I’ve been using that I’ve referred to as ActorModels. Not sure if I’ve seen it documented elsewhere.
Basically, it’s subclassing a model based on who’s using it and keeping the original model as slim as possible.
For instance a Product model might look like this:
class Product < ActiveRecord::Base
has_many :variations, dependent: :destroy
scope :published, -> {where(published: true)}
...
It contains the the information that either describes the model or is common to all subclasses but anything specific to a user type is in an “ActorModel” that inherits from it.
So, there might be a product for admins:
class Admin::Product < Product
# This scope is only useful within admin's context. For everyone else this might not matter.
scope :live_before, -> (date) {where("date(products.published_on) < ?", date)}
# has_many using an ActorModel for QualityIssues
has_many :quality_issues, class_name: "Admin::QualityIssues"
end
Or for buyers:
class Buyer::Product < Product
# Others might not use elastic for search
include ProductSearchable
# The admin doesn't need recommendations, the buyer does.
has_many :recommendations
end
Or for suppliers:
class Supplier::Product < Product
# They're the same issues as the admin but have different ActorModel
has_many :quality_issues, class_name: "Supplier::QualityIssues"
end
And finally for internal usage:
class Internal::Product < Product
# None of the users actually need these.
def self.index(id)
...
end
def to_index_json
...
end
end
The main benefit is of course that the large models that are used throughout end up being much smaller therefore much more readable, much easier to find what it is you’re looking for.
The main downside is that sometimes functionality might end up being duplicated but I haven’t found it to be that big of an issue so far.
In particular I’ve found this pattern to be useful for Products
, Orders
and Companies
.
Company
is a particularly interesting one because it’s got a few different perspectives: own account, buyer, supplier, and then for admin buyer and supplier as well.