Shawn Wilson
Shawn Wilson

Reputation: 1351

Limiting Multitenant Application Account By Number Of Users

So I am building out an application using Rails 4 and the Apartment Gem.

I am fairly new to multitenancy and have come to the point where I am building out user plans.

I have 4 main plans and I want each plan to limit the number of users that can be created, before telling the account owner or admin that they need to upgrade to register new users.

I think I am more stuck on where this should be done.. In my account model I have my constant for Plan:

PLAN = %w[responder first_responder patrol_pro guardian]

each of these plan_types (column I am saving to on sign up) have a set number of users that can be created, these are also set as constants below:

  RESPONDER_PLAN_USER_LIMIT = 6
  FIRST_RESPONDER_PLAN_USER_LIMIT = 12
  PATROL_PRO_PLAN_USER_LIMIT = 30
  GUARDIAN_PLAN_USER_LIMIT = 60

I have also created the below methods to verify the plan type however this seems clunky and was wondering if there was a way i could do this in one method instead of 4

  def responder_plan?
    self.plan_type == 'responder'
  end

  def first_responder_plan?
    self.plan_type == 'first_responder'
  end

  def patrol_pro_plan?
    self.plan_type == 'patrol_pro'
  end

  def guardian_plan?
    self.plan_type == 'guardian'
  end

Now for the last issue, to actually count the users attached to the account I was planning on using a Validator to do so, i am just un-sure of how to create the model method.

I was thinking something like this:

def over_user_limit?
  self.individual_plan? && self.users.count > INDIVIDUAL_USER_LIMIT
end

but I am stuck on how to do this with multiple user types?

Any assistance here would be greatly appreciated.

EDIT 1 : Error Message when trying to add the enum to my form

SyntaxError at /accounts/new
syntax error, unexpected tIDENTIFIER, expecting ')'
    first_responder:  12
                   ^
/Users/developer/Desktop/PatrolVault-Saas/PV_SAAS/app/models/plan.rb:7: syntax error, unexpected ':', expecting keyword_end
    patrol_pro:       30
               ^
/Users/developer/Desktop/PatrolVault-Saas/PV_SAAS/app/models/plan.rb:8: syntax error, unexpected ':', expecting keyword_end
    guardian:         60
             ^

and for brevity, here is my form field for it:

  <%= f.fields_for :plan do |plan| %>
  <div class="col-xs-12">
    <%= f.select :plan_type, options_for_select(Plan.plan_types.map {|k, v| [k.humanize.capitalize, k]}) %>
  </div>
  <% end %>

EDIT # 2 Remaining Error Message Referencing the Enum

Here is my Plan Model:

enum :plan_type, [:responder, :first_responder, :patrol_pro, :guardian]

USER_LIMITS = ActiveSupport::HashWithIndifferentAccess.new( responder: 6, first_responder: 12, patrol_pro: 30, guardian: 60 )

Here is the Error Message:

enter image description here

And the form item has not changed.

Upvotes: 0

Views: 53

Answers (1)

max
max

Reputation: 102026

The main issue is that the distribution of responsibilities is very muddled.

I would start by setting up two models with very clear responsibilities:

class Account < ActiveRecord::Base
  belongs_to :company
  has_one :plan
end

class Plan < ActiveRecord::Base
  belongs_to :account
end

The logic of defining the rules for different types of plans is definitely not the Account models job.

So lets implement the rules in the Plan class:

class Plan < ActiveRecord::Base
  belongs_to :account
  # declare the column plans.plan_type as integer.
  enum plan_type: [:responder, :first_responder, :patrol_pro, :guardian]
  USER_LIMITS = ActiveSupport::HashWithIndifferentAccess.new(
    responder:        6,
    first_responder:  12,
    patrol_pro:       30,
    guardian:         60
  )

  def user_limit
    USER_LIMITS[self.plan_type]
  end
end

You can then implement a validation:

class Plan < ActiveRecord::Base
  belongs_to :account
  # declare the column plans.plan_type as integer.
  enum plan_type: [:responder, :first_responder, :patrol_pro, :guardian]
  USER_LIMITS = ActiveSupport::HashWithIndifferentAccess.new(
    responder:        6,
    first_responder:  12,
    patrol_pro:       30,
    guardian:         60
  )

  validates :must_be_below_user_limit 

  def user_limit
    USER_LIMITS[self.plan_type]
  end

  def must_be_below_user_limit
   if self.account.users.size >= user_limit
     errors[:user_limit] = "can not more than #{user_limit} users"
   end
  end
end

Upvotes: 1

Related Questions