implementing multi tenancy

94 views
Skip to first unread message

Brian Rossetti

unread,
Mar 18, 2015, 11:02:08 AM3/18/15
to plutu...@googlegroups.com
Hey everyone, I have been working on a project that incorporates plutus and I am not attempting to switch multi-tenancy on. I ran the generated and ran the migration, now I have tenant_id on the plutus_accounts table, and I added the initializer. I am trying to use the Organization model in my project as the Tenant by specifying config.tenant_class = 'Organization'. here are my plutus associations on my Organization model:

class Organization < ActiveRecord::Base

  has_many :entries,       :class_name => 'Plutus::Entry'
  has_many :accounts,      :class_name => 'Plutus::Account'
  has_many :assets,        :class_name => 'Plutus::Asset'
  has_many :liabilities,   :class_name => 'Plutus::Liability'
  has_many :equities,      :class_name => 'Plutus::Equity'
  has_many :revenues,      :class_name => 'Plutus::Revenue'
  has_many :expenses,      :class_name => 'Plutus::Expense'

These associations worked before adding multi tenancy, but I was literally coping the source code for the Plutus models into my project under a plutus folder and adding associations to them and their tables.  My goal is to incorporate multi tenacy the proper way, but when I enable multi tenacny through plutus I get:

NoMethodError: undefined method `val' for #<Arel::Nodes::BindParam:0x007fa1dc974cf0>

I would also like to override the Amount class so I can add a belongs_to the Relationship model from my project and I am assuming I will need to do the same with Plutus Entry to enforce the association above "has_many :entries,       :class_name => 'Plutus::Entry'". Can anyone assist on the proper way to incorporate this behavior into my project?

thanks for any assistance you can provide, and for the gem.

here is my current schema for the models involved:

 create_table "plutus_accounts", force: :cascade do |t|
    t.string   "name"
    t.string   "type"
    t.boolean  "contra"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "number"
    t.string   "h2"
    t.string   "h3"
    t.string   "parent"
    t.string   "description"
    t.integer  "tenant_id"
  end

create_table "plutus_amounts", force: :cascade do |t|
    t.string  "type"
    t.integer "account_id"
    t.integer "entry_id"
    t.decimal "amount",          precision: 20, scale: 10
    t.integer "relationship_id"
  end

  add_index "plutus_amounts", ["relationship_id", "type"], name: "index_plutus_amounts_on_relationship_id_and_type"
  add_index "plutus_amounts", ["type"], name: "index_plutus_amounts_on_type"

  create_table "plutus_entries", force: :cascade do |t|
    t.string   "description"
    t.integer  "commercial_document_id"
    t.string   "commercial_document_type"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "plutus_entries", ["commercial_document_id", "commercial_document_type"], name: "index_entries_on_commercial_doc"


create_table "organizations", force: :cascade do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

 create_table "relationships", force: :cascade do |t|
    t.string   "entity_name"
    t.string   "first_name"
    t.string   "last_name"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.string   "tax_id"
    t.integer  "customer_terms"
    t.string   "w9"
    t.string   "routing_number"
    t.string   "ssn"
    t.integer  "organization_id"
    t.boolean  "is_org"
    t.boolean  "is_vendor",       default: false
    t.boolean  "is_customer",     default: false
    t.boolean  "is_bank",         default: false
    t.boolean  "is_employee",     default: false
    t.boolean  "is_govt",         default: false
    t.integer  "vendor_terms"
    t.boolean  "is_investor",     default: false
    t.string   "salutation"
    t.string   "screen_name"
  end

mbulat

unread,
Mar 18, 2015, 11:28:49 AM3/18/15
to plutu...@googlegroups.com
Hi Brian, 

I'm afraid I can't entirely help, since I don't utilize the multi-tenancy support myself. (iffyuva on github supplied the code) My only suggestion is that you don't necessarily need to use the built in multi-tenancy support, and you could turn it off, and supply your own mechanism, which may make things easier.

I usually point people to the rails guide on improving engine functionality when people want to do something complex like this:


You'll notice that you don't need to copy the whole class into your project, but can simply extend them with decorator code. I'd recommend using ActiveSupport::Concern for the decoration. So I think you should be able to modify the classes this way to support any multi-tenancy associations you might need.

Brian Rossetti

unread,
Mar 19, 2015, 2:25:14 AM3/19/15
to plutu...@googlegroups.com
Thanks for the quick response! i ended up incorporating the engine and switching multitenancy on, my issue was that i needed to use the foreign_key: to point my organization class at the tenant id like so: 

class Organization < ActiveRecord::Base
  has_many :entries,          :class_name => 'Plutus::Entry',       foreign_key: "tenant_id" 
  has_many :accounts,      :class_name => 'Plutus::Account',   foreign_key: "tenant_id"
end

conig/initializers/plutus.rb

Plutus.config do |config|
  config.enable_tenancy = true
  config.tenant_class = 'Organization'
end

incorporating the engine also worked for adding associations, but i used the class_eval, not too comfortable with Concerns at the moment.

lib/plutus/engine.rb

module Plutus
  class Engine < ::Rails::Engine
    isolate_namespace Plutus
 
    config.to_prepare do
      Dir.glob(Rails.root + "app/decorators/**/*_decorator*.rb").each do |c|
        require_dependency(c)
      end
    end
  end
end


decorators/models/plutus/amount.rb

Plutus::Amount.class_eval do
  belongs_to :relationship
end

thanks again for your help, I posted another question about entries, mine seem to be failing, was hoping you might be able to take a look. again thank you!

Brian
Reply all
Reply to author
Forward
0 new messages