ruby-on-railsruby-on-rails-4acts-as-tenant

Extending gem/engine models to include acts_as_tenant from main app


There are a few post on this subject but the light has not turned on yet.

I'm trying to extend a rails gem/engine Plutus to use acts_as_tenant

Plutus provides a double entry accounting system for an application. One of the limitations is that the design allows for only one customer or one set of books. What I am trying to do is add multi-tenancy using acts_as_tenant with as little as possible modifications to the Plutus engine. The goal is not to significantly alter Plutus with a different fork, but to add a few optional methods or attributes to Plutus that are only used if you want multiple accounts.

I have it semi-working, but need help in finding where to put stuff and help in clear up what is not working. The condensed Plutus models are:

class Account < ActiveRecord::Base
    has_many :credit_amounts, :extend => AmountsExtension
    has_many :debit_amounts, :extend => AmountsExtension
    has_many :credit_transactions, :through => :credit_amounts, :source => :transaction
    has_many :debit_transactions, :through => :debit_amounts, :source => :transaction
end

class Amount < ActiveRecord::Base
  belongs_to :transaction
  belongs_to :account
end

class Transaction < ActiveRecord::Base
   belongs_to :commercial_document, :polymorphic => true
   has_many :credit_amounts, :extend => AmountsExtension
   has_many :debit_amounts, :extend => AmountsExtension
   has_many :credit_accounts, :through => :credit_amounts, :source => :account
   has_many :debit_accounts, :through => :debit_amounts, :source => :account
end

Then sti classes on Account: Asset, Equity, Expense, Liability, Revenue and sti classes on Amount: DebitAmount, CreditAmount. This is a little beyond my rails knowledge but this may be on of the most compact double entry schemes I've ever seen (I'm not an accountant, but I have had to add accounting features on apps in the past).

Semi-working means that the only thing I've modified in Plutus is adding a tenant_id to the three models and getting acts_as_tenant to extend two of the three models. From the console on the main application I've found that:

Plutus::Account.acts_as_tenant(:tenant)
Plutus::Amount.acts_as_tenant(:tenant)
Plutus::Transaction.acts_as_tenant(:tenant)

works for Account and Transaction, but errors on Amount with uninitialized constant Transaction, and I'm not sure why. Any ideas?

I've read the rails guide on engines and extending with decorators or concerns, but have not figured out how to send acts_as_tenant(:tenant) to the model using those approaches. Where would I put those three lines of code in the main application (providing I figure out how to get Amount to work!)?

Is there a better approach?

I still have a few class methods that I will have to extend or modify, but no use trying that until I get over this first hurdle.


Solution

  • The problem was that Plutus is a name-spaced engine, and while it works fine within the engine, calling it from outside the engine (main app) could raise conflicts.

    To fix it, a class_name option was added to the associations.

    module Plutus
        class Amount < ActiveRecord::Base
          belongs_to :transaction, class_name:"Plutus::Transaction"
          belongs_to :account, class_name:"Plutus::Account"
    
          validates_presence_of :type, :amount, :transaction, :account
        end
    end
    

    Still never figured out the best place to stick the ActsAsTenant calls. I stuck them in the Concerns directory and they didn't get called. Ended up putting them in my Tenant model and all is fine.